diff --git a/decus/lt87a/gce/bulletin0131/.listing b/decus/lt87a/gce/bulletin0131/.listing
new file mode 100644
index 0000000000000000000000000000000000000000..c2daac8fb97925ac05bbb8a91c27c8f61fdd0ae9
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/.listing differ
diff --git a/decus/lt87a/gce/bulletin0131/bulallmacs.mar b/decus/lt87a/gce/bulletin0131/bulallmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..c269510847db9835536ecb0c67f16048c9200da9
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulallmacs.mar differ
diff --git a/decus/lt87a/gce/bulletin0131/bullcoms.hlp b/decus/lt87a/gce/bulletin0131/bullcoms.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..eaeddedf74d3c99884f6bf395590b639728e2bf9
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bullcoms.hlp differ
diff --git a/decus/lt87a/gce/bulletin0131/bullet.com b/decus/lt87a/gce/bulletin0131/bullet.com
new file mode 100755
index 0000000000000000000000000000000000000000..dd3f950ae0b95fdd68a2fbf6d5a2bd64cea07180
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bullet.com differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin.for b/decus/lt87a/gce/bulletin0131/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..d60faf73c798fe40d0fac9737ac4afa12e7320de
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin0.for b/decus/lt87a/gce/bulletin0131/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..e9b3bbbb5ee8fd3135704bae098be57f027fb99e
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin0.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin1.for b/decus/lt87a/gce/bulletin0131/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..6fb64808cec81c1aeb0fe6de5710811ead9d38b3
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin1.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin2.for b/decus/lt87a/gce/bulletin0131/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..6f94b729d563271b5b30177ab3b1458ed1c5f59b
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin2.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin3.for b/decus/lt87a/gce/bulletin0131/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..8682c36c555adce3b85f0f2973ee43f554af406f
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin3.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin4.for b/decus/lt87a/gce/bulletin0131/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..f84f9bbadd94609c9a477736795616a56db10a3b
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin4.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin5.for b/decus/lt87a/gce/bulletin0131/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..2f6d28741bd729cfb8f0b3ceaebaad71c30be8dc
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin5.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletin6.for b/decus/lt87a/gce/bulletin0131/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..67d3ff3d5057371e23b34a9473553b535a242914
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletin6.for differ
diff --git a/decus/lt87a/gce/bulletin0131/bulletinann.txt b/decus/lt87a/gce/bulletin0131/bulletinann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..464737387f9357785b2dbd4849fd5c082b07a99a
Binary files /dev/null and b/decus/lt87a/gce/bulletin0131/bulletinann.txt differ
diff --git a/decus/lt89b1/bulletin/aaareadme.1st b/decus/lt89b1/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..4dfdbed2b5ea3342e8013c622d60c48eb3460e46
Binary files /dev/null and b/decus/lt89b1/bulletin/aaareadme.1st differ
diff --git a/decus/lt89b1/bulletin/aaareadme.txt b/decus/lt89b1/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..be8895ca770f327c2a82af3de5d4bce56cc9a1c1
Binary files /dev/null and b/decus/lt89b1/bulletin/aaareadme.txt differ
diff --git a/decus/lt89b1/bulletin/board_digest.com b/decus/lt89b1/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/lt89b1/bulletin/board_digest.com differ
diff --git a/decus/lt89b1/bulletin/board_special.com b/decus/lt89b1/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6ff014483565e3b6f13a05e42ba24b8178f9da3
Binary files /dev/null and b/decus/lt89b1/bulletin/board_special.com differ
diff --git a/decus/lt89b1/bulletin/bullcom.cld b/decus/lt89b1/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..9d1d9230c1a7bef17879fbf702a2230ea5b6c939
Binary files /dev/null and b/decus/lt89b1/bulletin/bullcom.cld differ
diff --git a/decus/lt89b1/bulletin/bullcoms1.hlp b/decus/lt89b1/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..5f49e92caac1ef6f9392156fb36d9035c9c56313
Binary files /dev/null and b/decus/lt89b1/bulletin/bullcoms1.hlp differ
diff --git a/decus/lt89b1/bulletin/bullcoms2.hlp b/decus/lt89b1/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..21b8a4d349cbb6737a5e2a241bc72c5496cb9aa7
Binary files /dev/null and b/decus/lt89b1/bulletin/bullcoms2.hlp differ
diff --git a/decus/lt89b1/bulletin/bullet1.com b/decus/lt89b1/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..9b288bb027e0d22aca3fde08ba1005cfe0e24b3d
Binary files /dev/null and b/decus/lt89b1/bulletin/bullet1.com differ
diff --git a/decus/lt89b1/bulletin/bullet2.com b/decus/lt89b1/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..606ccf139f7a0ecdda52484546187ec175d5367a
Binary files /dev/null and b/decus/lt89b1/bulletin/bullet2.com differ
diff --git a/decus/lt89b1/bulletin/bulletin.cld b/decus/lt89b1/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..93d3d16ef7ce0323dff6533dee70f5111caf79fc
Binary files /dev/null and b/decus/lt89b1/bulletin/bulletin.cld differ
diff --git a/decus/lt89b1/bulletin/bulletin.com b/decus/lt89b1/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/lt89b1/bulletin/bulletin.com differ
diff --git a/decus/lt89b1/bulletin/bulletin.hlp b/decus/lt89b1/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..2d590a6cbe0289b30f7a801351d9e6caba2375b3
Binary files /dev/null and b/decus/lt89b1/bulletin/bulletin.hlp differ
diff --git a/decus/lt89b1/bulletin/bulletin.info b/decus/lt89b1/bulletin/bulletin.info
new file mode 100755
index 0000000000000000000000000000000000000000..7b47ba8c7138946db2b5a0f2c4f5a73e024e3876
Binary files /dev/null and b/decus/lt89b1/bulletin/bulletin.info differ
diff --git a/decus/lt89b1/bulletin/bulletin.lnk b/decus/lt89b1/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..6ad68a94da3a5be74b7503d7c8dea7da93e6b980
Binary files /dev/null and b/decus/lt89b1/bulletin/bulletin.lnk differ
diff --git a/decus/lt89b1/bulletin/bullmain.cld b/decus/lt89b1/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..eb8b4d47cc517d79c00e88cc074666e689fb6f83
Binary files /dev/null and b/decus/lt89b1/bulletin/bullmain.cld differ
diff --git a/decus/lt89b1/bulletin/bullstart.com b/decus/lt89b1/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/lt89b1/bulletin/bullstart.com differ
diff --git a/decus/lt89b1/bulletin/create.com b/decus/lt89b1/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..3e3c722b40ccf8ff1c10c3d6338839eace5d63e9
Binary files /dev/null and b/decus/lt89b1/bulletin/create.com differ
diff --git a/decus/lt89b1/bulletin/dclremote.com b/decus/lt89b1/bulletin/dclremote.com
new file mode 100755
index 0000000000000000000000000000000000000000..2c8b5ba8e1f1d24135d8f62e8977667d0ab5ff68
Binary files /dev/null and b/decus/lt89b1/bulletin/dclremote.com differ
diff --git a/decus/lt89b1/bulletin/handout.txt b/decus/lt89b1/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/lt89b1/bulletin/handout.txt differ
diff --git a/decus/lt89b1/bulletin/install.com b/decus/lt89b1/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..a94bca0bb58982626705b4e6208eec9863702ce0
Binary files /dev/null and b/decus/lt89b1/bulletin/install.com differ
diff --git a/decus/lt89b1/bulletin/install_remote.com b/decus/lt89b1/bulletin/install_remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..93ae3b1bb784e75b1617e2af2b092bfa1cae07ef
Binary files /dev/null and b/decus/lt89b1/bulletin/install_remote.com differ
diff --git a/decus/lt89b1/bulletin/instruct.com b/decus/lt89b1/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/lt89b1/bulletin/instruct.com differ
diff --git a/decus/lt89b1/bulletin/instruct.txt b/decus/lt89b1/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/lt89b1/bulletin/instruct.txt differ
diff --git a/decus/lt89b1/bulletin/login.com b/decus/lt89b1/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..db86b1d3c4c892235d5c896df3d265f7887f214a
Binary files /dev/null and b/decus/lt89b1/bulletin/login.com differ
diff --git a/decus/lt89b1/bulletin/makefile b/decus/lt89b1/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..f3664e6af03224500c77268daa888f7db116dd76
Binary files /dev/null and b/decus/lt89b1/bulletin/makefile differ
diff --git a/decus/lt89b1/bulletin/nonsystem.txt b/decus/lt89b1/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/lt89b1/bulletin/nonsystem.txt differ
diff --git a/decus/lt89b1/bulletin/pmdf.com b/decus/lt89b1/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..79102ef549d5c1d93a40b9cb2a7746098f87c161
Binary files /dev/null and b/decus/lt89b1/bulletin/pmdf.com differ
diff --git a/decus/lt89b1/bulletin/remote.com b/decus/lt89b1/bulletin/remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..5cc6fbf88780364f4639e3581d10bf442e7dc58e
Binary files /dev/null and b/decus/lt89b1/bulletin/remote.com differ
diff --git a/decus/lt89b1/bulletin/writemsg.txt b/decus/lt89b1/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6ee4ec02e151fc32828c4e890830eee127cf5da3
Binary files /dev/null and b/decus/lt89b1/bulletin/writemsg.txt differ
diff --git a/decus/net/89b/bulletin/allmacs.mar b/decus/net/89b/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..a70ab7e91b5b259ba95b1da71bae0ddb13a22f46
Binary files /dev/null and b/decus/net/89b/bulletin/allmacs.mar differ
diff --git a/decus/net/89b/bulletin/bullcoms1.hlp b/decus/net/89b/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..f097a8b7c3865cf101a57bd6ad58f0f744722c99
Binary files /dev/null and b/decus/net/89b/bulletin/bullcoms1.hlp differ
diff --git a/decus/net/89b/bulletin/bullcoms2.hlp b/decus/net/89b/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..b888cd92980ae91357c3f5e054fd44439340ef67
Binary files /dev/null and b/decus/net/89b/bulletin/bullcoms2.hlp differ
diff --git a/decus/net/89b/bulletin/bullet1.com b/decus/net/89b/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..4aefc817af99919d1a3f9bdc43f1e923042eeb00
Binary files /dev/null and b/decus/net/89b/bulletin/bullet1.com differ
diff --git a/decus/net/89b/bulletin/bullet2.com b/decus/net/89b/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..abbedfc5477a478573d84d8fba3faae1a5bb06df
Binary files /dev/null and b/decus/net/89b/bulletin/bullet2.com differ
diff --git a/decus/net/89b/bulletin/bulletin.for b/decus/net/89b/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..b3ae224cca9e349fec50681308473e6c3faee3ce
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin.for differ
diff --git a/decus/net/89b/bulletin/bulletin0.for b/decus/net/89b/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..a820d27aa89b5bc6b58d73f94e79106975aeb326
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin0.for differ
diff --git a/decus/net/89b/bulletin/bulletin1.for b/decus/net/89b/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..6cc00f005eaa119741155eb18036cfee185d0a19
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin1.for differ
diff --git a/decus/net/89b/bulletin/bulletin2.for b/decus/net/89b/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..3c09b99a43605625c1ae7a6413e3caa14e57b6c1
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin2.for differ
diff --git a/decus/net/89b/bulletin/bulletin3.for b/decus/net/89b/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..ee80c8d9bd9aaa949a007f62dfab7c680080b69e
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin3.for differ
diff --git a/decus/net/89b/bulletin/bulletin4.for b/decus/net/89b/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..8238fa7d8c7718fa830af39303c564f4bb861db7
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin4.for differ
diff --git a/decus/net/89b/bulletin/bulletin5.for b/decus/net/89b/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..bd3de8d7c63b679d111a6e6ddc243801bbf29ae1
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin5.for differ
diff --git a/decus/net/89b/bulletin/bulletin6.for b/decus/net/89b/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..2a9131bbd0dfe3e0b06b54278ab78a71a970b00b
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin6.for differ
diff --git a/decus/net/89b/bulletin/bulletin7.for b/decus/net/89b/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..5d408e622fa0b3989ac8659c3fc6fb2d873c9492
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin7.for differ
diff --git a/decus/net/89b/bulletin/bulletin8.for b/decus/net/89b/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..adba6b46f24142f2d9c4257a91ab8899a922b2aa
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin8.for differ
diff --git a/decus/net/89b/bulletin/bulletin9.for b/decus/net/89b/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..a7d00dbbd5c1209e0a61c391c0596bfe0d430a14
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin9.for differ
diff --git a/decus/net/89b/bulletin/bulletin_ann.txt b/decus/net/89b/bulletin/bulletin_ann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..996b51d5f7c63ccaa0a7be4fde4efa8bcd204ea9
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin_ann.txt differ
diff --git a/decus/net/89b/bulletin/bulletin_howto_get.txt b/decus/net/89b/bulletin/bulletin_howto_get.txt
new file mode 100755
index 0000000000000000000000000000000000000000..f40baa5ff57611529a6ee8862a819269f52d9d33
Binary files /dev/null and b/decus/net/89b/bulletin/bulletin_howto_get.txt differ
diff --git a/decus/net/89b/bulletin/pmdf.com b/decus/net/89b/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..a756e6d06a9a774b27b1b075b50740eb2f342490
Binary files /dev/null and b/decus/net/89b/bulletin/pmdf.com differ
diff --git a/decus/vax82b/icr/bulletin/aaareadme.txt b/decus/vax82b/icr/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..a962ff0133e62b09e13dff65dce885aed079f16d
Binary files /dev/null and b/decus/vax82b/icr/bulletin/aaareadme.txt differ
diff --git a/decus/vax82b/icr/bulletin/bc.com b/decus/vax82b/icr/bulletin/bc.com
new file mode 100755
index 0000000000000000000000000000000000000000..451b9bc724814f5fe992a6b6ec6a78f95a62dc9f
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bc.com differ
diff --git a/decus/vax82b/icr/bulletin/bcmail.com b/decus/vax82b/icr/bulletin/bcmail.com
new file mode 100755
index 0000000000000000000000000000000000000000..2316d8299619b37f273210d9b6edb6832fec0f6d
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bcmail.com differ
diff --git a/decus/vax82b/icr/bulletin/bcmail.txt b/decus/vax82b/icr/bulletin/bcmail.txt
new file mode 100755
index 0000000000000000000000000000000000000000..efc8bc9590c6c54017be5ba83346c14e810fdbea
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bcmail.txt differ
diff --git a/decus/vax82b/icr/bulletin/build.com b/decus/vax82b/icr/bulletin/build.com
new file mode 100755
index 0000000000000000000000000000000000000000..fc5de3ce0922eaae3a31a81f012d5a45ed48e671
Binary files /dev/null and b/decus/vax82b/icr/bulletin/build.com differ
diff --git a/decus/vax82b/icr/bulletin/bull.for b/decus/vax82b/icr/bulletin/bull.for
new file mode 100755
index 0000000000000000000000000000000000000000..02798c172176d71df89e42f515783e74f115745c
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bull.for differ
diff --git a/decus/vax82b/icr/bulletin/bullcheck.for b/decus/vax82b/icr/bulletin/bullcheck.for
new file mode 100755
index 0000000000000000000000000000000000000000..ed5b51881205d39ce4a531e15089323cde47a571
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bullcheck.for differ
diff --git a/decus/vax82b/icr/bulletin/bullcom.for b/decus/vax82b/icr/bulletin/bullcom.for
new file mode 100755
index 0000000000000000000000000000000000000000..74f41edce4f7f9b2f55a331d90399565875c6365
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bullcom.for differ
diff --git a/decus/vax82b/icr/bulletin/bulletin.hlp b/decus/vax82b/icr/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..e3c3849dcd9d544a29dac5c74b0b3450e8086389
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bulletin.hlp differ
diff --git a/decus/vax82b/icr/bulletin/bulletin.rno b/decus/vax82b/icr/bulletin/bulletin.rno
new file mode 100755
index 0000000000000000000000000000000000000000..b1b537bac08a14e0069ca0760da9ebecd249f705
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bulletin.rno differ
diff --git a/decus/vax82b/icr/bulletin/bullintro.rno b/decus/vax82b/icr/bulletin/bullintro.rno
new file mode 100755
index 0000000000000000000000000000000000000000..58985918e8229b3449f4e1ea8341f93e230c3898
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bullintro.rno differ
diff --git a/decus/vax82b/icr/bulletin/bullintro.txt b/decus/vax82b/icr/bulletin/bullintro.txt
new file mode 100755
index 0000000000000000000000000000000000000000..cd314b3ac69af14c2f5932e6d628675996cacfc9
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bullintro.txt differ
diff --git a/decus/vax82b/icr/bulletin/bullparse.mar b/decus/vax82b/icr/bulletin/bullparse.mar
new file mode 100755
index 0000000000000000000000000000000000000000..5b9180f9f26205bb3454e5bfb4d64e432dbaff14
Binary files /dev/null and b/decus/vax82b/icr/bulletin/bullparse.mar differ
diff --git a/decus/vax85c/bulletin/aaareadme.doc b/decus/vax85c/bulletin/aaareadme.doc
new file mode 100755
index 0000000000000000000000000000000000000000..d68fed3a3662dab52505ee0510d650dc301b219f
Binary files /dev/null and b/decus/vax85c/bulletin/aaareadme.doc differ
diff --git a/decus/vax85c/bulletin/aaareadme.rno b/decus/vax85c/bulletin/aaareadme.rno
new file mode 100755
index 0000000000000000000000000000000000000000..970aaa62e87ca354216073e13f7f404ac060dcb9
Binary files /dev/null and b/decus/vax85c/bulletin/aaareadme.rno differ
diff --git a/decus/vax85c/bulletin/aaareadme.txt b/decus/vax85c/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..dc6b9c2443044d023b49b266273b6cab111893e9
Binary files /dev/null and b/decus/vax85c/bulletin/aaareadme.txt differ
diff --git a/decus/vax85c/bulletin/announce.mai b/decus/vax85c/bulletin/announce.mai
new file mode 100755
index 0000000000000000000000000000000000000000..f72d2f89017b1facede2dfe28dd1759a17fd3738
Binary files /dev/null and b/decus/vax85c/bulletin/announce.mai differ
diff --git a/decus/vax85c/bulletin/bboard.com b/decus/vax85c/bulletin/bboard.com
new file mode 100755
index 0000000000000000000000000000000000000000..5a538ed8bdf42b09adc3bf23950aedd46835b47c
Binary files /dev/null and b/decus/vax85c/bulletin/bboard.com differ
diff --git a/decus/vax85c/bulletin/bulet.com b/decus/vax85c/bulletin/bulet.com
new file mode 100755
index 0000000000000000000000000000000000000000..b3d9f2f8129496c6aa614ab03b5352308687ad0b
Binary files /dev/null and b/decus/vax85c/bulletin/bulet.com differ
diff --git a/decus/vax85c/bulletin/bullcom.cld b/decus/vax85c/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..468a5619bb558437c4f627fba0986e61ae165865
Binary files /dev/null and b/decus/vax85c/bulletin/bullcom.cld differ
diff --git a/decus/vax85c/bulletin/bullcoms.hlp b/decus/vax85c/bulletin/bullcoms.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..47b3de14649e1c06de5ac04e7b164e2d25395ba7
Binary files /dev/null and b/decus/vax85c/bulletin/bullcoms.hlp differ
diff --git a/decus/vax85c/bulletin/bulldir.inc b/decus/vax85c/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..8f45690da5f3fe04a50e15f949f20726fc4038b5
Binary files /dev/null and b/decus/vax85c/bulletin/bulldir.inc differ
diff --git a/decus/vax85c/bulletin/bullet.mai b/decus/vax85c/bulletin/bullet.mai
new file mode 100755
index 0000000000000000000000000000000000000000..f08697fee46697477225350331a16960683efc4f
Binary files /dev/null and b/decus/vax85c/bulletin/bullet.mai differ
diff --git a/decus/vax85c/bulletin/bulletin.com b/decus/vax85c/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..a3556665c24234b4633525a079dec277097be950
Binary files /dev/null and b/decus/vax85c/bulletin/bulletin.com differ
diff --git a/decus/vax85c/bulletin/bulletin.for b/decus/vax85c/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..885fbdc4a7f90b3e02c50be9a6cd69971156a6fc
Binary files /dev/null and b/decus/vax85c/bulletin/bulletin.for differ
diff --git a/decus/vax85c/bulletin/bulletin.hlp b/decus/vax85c/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..a7f32854c2771cd571da92d4d7cd34d4ea94deee
Binary files /dev/null and b/decus/vax85c/bulletin/bulletin.hlp differ
diff --git a/decus/vax85c/bulletin/bulletin.lnk b/decus/vax85c/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..662133d873cea3fe9c949e783eae8536a07293d8
Binary files /dev/null and b/decus/vax85c/bulletin/bulletin.lnk differ
diff --git a/decus/vax85c/bulletin/bulletin.txt b/decus/vax85c/bulletin/bulletin.txt
new file mode 100755
index 0000000000000000000000000000000000000000..7ac791cb74746e6c33effe4062f9b1cb443ea080
Binary files /dev/null and b/decus/vax85c/bulletin/bulletin.txt differ
diff --git a/decus/vax85c/bulletin/bullfiles.inc b/decus/vax85c/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..6602824251dcd0c0ce76619f95d0079c40374343
Binary files /dev/null and b/decus/vax85c/bulletin/bullfiles.inc differ
diff --git a/decus/vax85c/bulletin/bullflag.inc b/decus/vax85c/bulletin/bullflag.inc
new file mode 100755
index 0000000000000000000000000000000000000000..8b76f6964fa03c6fe1acfcdcf224d151c99d5583
Binary files /dev/null and b/decus/vax85c/bulletin/bullflag.inc differ
diff --git a/decus/vax85c/bulletin/bullmain.cld b/decus/vax85c/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..e4d201b295d752488c37185c3a163b520555cb70
Binary files /dev/null and b/decus/vax85c/bulletin/bullmain.cld differ
diff --git a/decus/vax85c/bulletin/bullstart.com b/decus/vax85c/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c1419f0f0ab0ef3eb8e85a33a3ade1435da0a927
Binary files /dev/null and b/decus/vax85c/bulletin/bullstart.com differ
diff --git a/decus/vax85c/bulletin/bullsubs.for b/decus/vax85c/bulletin/bullsubs.for
new file mode 100755
index 0000000000000000000000000000000000000000..79ab13cf6344ca1f683af4bbcc4112ff9e1a7f1e
Binary files /dev/null and b/decus/vax85c/bulletin/bullsubs.for differ
diff --git a/decus/vax85c/bulletin/bulluser.inc b/decus/vax85c/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..05c031521d9dc1484c43ff5ad50823ecd091c849
Binary files /dev/null and b/decus/vax85c/bulletin/bulluser.inc differ
diff --git a/decus/vax85c/bulletin/clidef.mar b/decus/vax85c/bulletin/clidef.mar
new file mode 100755
index 0000000000000000000000000000000000000000..4198cbd386e42ccd6991df1b8f848fdb00f2541b
Binary files /dev/null and b/decus/vax85c/bulletin/clidef.mar differ
diff --git a/decus/vax85c/bulletin/create.com b/decus/vax85c/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..bba6be3750c5e05f30b13bffb99a5ea92ed79c77
Binary files /dev/null and b/decus/vax85c/bulletin/create.com differ
diff --git a/decus/vax85c/bulletin/hpwd.mar b/decus/vax85c/bulletin/hpwd.mar
new file mode 100755
index 0000000000000000000000000000000000000000..5c03060da0c509072ab86577f149f21b539d94d1
Binary files /dev/null and b/decus/vax85c/bulletin/hpwd.mar differ
diff --git a/decus/vax85c/bulletin/install.com b/decus/vax85c/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..466b6acd0aebdf8e0e741d5b8cf4a23c59fe2e27
Binary files /dev/null and b/decus/vax85c/bulletin/install.com differ
diff --git a/decus/vax85c/bulletin/instruct.txt b/decus/vax85c/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..67e5e4ecab23d7864ce5599eaa681798050f3b65
Binary files /dev/null and b/decus/vax85c/bulletin/instruct.txt differ
diff --git a/decus/vax85c/bulletin/login.com b/decus/vax85c/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..ee65512819c59e3446f854c92eb69cd6c9f73a97
Binary files /dev/null and b/decus/vax85c/bulletin/login.com differ
diff --git a/decus/vax85c/bulletin/netfiles/announce.mai b/decus/vax85c/bulletin/netfiles/announce.mai
new file mode 100755
index 0000000000000000000000000000000000000000..f72d2f89017b1facede2dfe28dd1759a17fd3738
Binary files /dev/null and b/decus/vax85c/bulletin/netfiles/announce.mai differ
diff --git a/decus/vax85c/bulletin/netfiles/file1.mai b/decus/vax85c/bulletin/netfiles/file1.mai
new file mode 100755
index 0000000000000000000000000000000000000000..e1215abdf2414c4874b4a1502ed792a1fa29881e
Binary files /dev/null and b/decus/vax85c/bulletin/netfiles/file1.mai differ
diff --git a/decus/vax85c/bulletin/netfiles/file2.mai b/decus/vax85c/bulletin/netfiles/file2.mai
new file mode 100755
index 0000000000000000000000000000000000000000..35d009350226ad0914e025df62657e3c0f3acc14
Binary files /dev/null and b/decus/vax85c/bulletin/netfiles/file2.mai differ
diff --git a/decus/vax85c/bulletin/netfiles/file3.mai b/decus/vax85c/bulletin/netfiles/file3.mai
new file mode 100755
index 0000000000000000000000000000000000000000..334c0ddfdaa4a471ff4d9434793dba33f7a95a2e
Binary files /dev/null and b/decus/vax85c/bulletin/netfiles/file3.mai differ
diff --git a/decus/vax85c/bulletin/netfiles/file4.mai b/decus/vax85c/bulletin/netfiles/file4.mai
new file mode 100755
index 0000000000000000000000000000000000000000..71d1efe0b0891d73e5e2118e3f9ad4259798a7d1
Binary files /dev/null and b/decus/vax85c/bulletin/netfiles/file4.mai differ
diff --git a/decus/vax85c/bulletin/netfiles/file5.mai b/decus/vax85c/bulletin/netfiles/file5.mai
new file mode 100755
index 0000000000000000000000000000000000000000..b289ddd986f99b338c420ef733c609d4d502afb8
Binary files /dev/null and b/decus/vax85c/bulletin/netfiles/file5.mai differ
diff --git a/decus/vax85c/bulletin/setuic.mar b/decus/vax85c/bulletin/setuic.mar
new file mode 100755
index 0000000000000000000000000000000000000000..4e7a03daf49d324f3af8d4791e951aa02343a717
Binary files /dev/null and b/decus/vax85c/bulletin/setuic.mar differ
diff --git a/decus/vax85c/bulletin/setuser.mar b/decus/vax85c/bulletin/setuser.mar
new file mode 100755
index 0000000000000000000000000000000000000000..a4328b77f7bd3c6370ba18ca12a106df06838a1f
Binary files /dev/null and b/decus/vax85c/bulletin/setuser.mar differ
diff --git a/decus/vax85c/bulletin/startup.com b/decus/vax85c/bulletin/startup.com
new file mode 100755
index 0000000000000000000000000000000000000000..7dced9b27be4b69ccf3c25a3d7e7f0940a0a437c
Binary files /dev/null and b/decus/vax85c/bulletin/startup.com differ
diff --git a/decus/vax85c/bulletin/useropen.mar b/decus/vax85c/bulletin/useropen.mar
new file mode 100755
index 0000000000000000000000000000000000000000..7149bc7a49393faac534778627a84b1c27faa020
Binary files /dev/null and b/decus/vax85c/bulletin/useropen.mar differ
diff --git a/decus/vax86c/bulletin/aaareadme.txt b/decus/vax86c/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..085bf435f8573109f5ed3b0c6ec3305cbb83eae9
Binary files /dev/null and b/decus/vax86c/bulletin/aaareadme.txt differ
diff --git a/decus/vax86c/bulletin/allmacs.mar b/decus/vax86c/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..e3c7fbcb0fa4b9dc86d15e17d31c09119c3db1d1
Binary files /dev/null and b/decus/vax86c/bulletin/allmacs.mar differ
diff --git a/decus/vax86c/bulletin/bullet.com b/decus/vax86c/bulletin/bullet.com
new file mode 100755
index 0000000000000000000000000000000000000000..da65dc79cd5450b18a68ef217d31ca096489eb7a
Binary files /dev/null and b/decus/vax86c/bulletin/bullet.com differ
diff --git a/decus/vax86c/bulletin/bulletin.for b/decus/vax86c/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..b3834355bf33dd1607393d0a437fd68feaa30fcd
Binary files /dev/null and b/decus/vax86c/bulletin/bulletin.for differ
diff --git a/decus/vax86c/bulletin/bulletin.txt b/decus/vax86c/bulletin/bulletin.txt
new file mode 100755
index 0000000000000000000000000000000000000000..046b4d6d20f15328f2c6c8180a33afd36a5cb81c
Binary files /dev/null and b/decus/vax86c/bulletin/bulletin.txt differ
diff --git a/decus/vax86c/bulletin/bullsub0.for b/decus/vax86c/bulletin/bullsub0.for
new file mode 100755
index 0000000000000000000000000000000000000000..9a5f81cd6db207329ccaaec0849d62b9dcb44fed
Binary files /dev/null and b/decus/vax86c/bulletin/bullsub0.for differ
diff --git a/decus/vax86c/bulletin/bullsub1.for b/decus/vax86c/bulletin/bullsub1.for
new file mode 100755
index 0000000000000000000000000000000000000000..fb4466b26bdbbf043e70f85a13094715270285a0
Binary files /dev/null and b/decus/vax86c/bulletin/bullsub1.for differ
diff --git a/decus/vax86c/bulletin/bullsub2.for b/decus/vax86c/bulletin/bullsub2.for
new file mode 100755
index 0000000000000000000000000000000000000000..f59dd75226c23f85d01914a4dfdb4059c80a929c
Binary files /dev/null and b/decus/vax86c/bulletin/bullsub2.for differ
diff --git a/decus/vax86c/bulletin/bullsub3.for b/decus/vax86c/bulletin/bullsub3.for
new file mode 100755
index 0000000000000000000000000000000000000000..96de09ea33c321177dcfec7a67dcd8e8c241e07e
Binary files /dev/null and b/decus/vax86c/bulletin/bullsub3.for differ
diff --git a/decus/vax86d/fermlib/news687/bulletin.com b/decus/vax86d/fermlib/news687/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..0a7ce43448f8b45db8462f4cd78af3732a0c7fa2
Binary files /dev/null and b/decus/vax86d/fermlib/news687/bulletin.com differ
diff --git a/decus/vax87a/bbs/bulletin.for b/decus/vax87a/bbs/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..340f90d7b8b26ecbdc287901a931a08d6fdb6202
Binary files /dev/null and b/decus/vax87a/bbs/bulletin.for differ
diff --git a/decus/vax87a/bbs/bulletin0.for b/decus/vax87a/bbs/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..44a8298606ad86ae08df668bdde0e36f5f9b232b
Binary files /dev/null and b/decus/vax87a/bbs/bulletin0.for differ
diff --git a/decus/vax87a/bbs/bulletin1.for b/decus/vax87a/bbs/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..eae9dcb361333fa2365c7551095122fb9a287596
Binary files /dev/null and b/decus/vax87a/bbs/bulletin1.for differ
diff --git a/decus/vax87a/bbs/bulletin2.for b/decus/vax87a/bbs/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..c4b4333482ade8789a5c2ca5e952f3b271a3b6f5
Binary files /dev/null and b/decus/vax87a/bbs/bulletin2.for differ
diff --git a/decus/vax87a/bbs/bulletin3.for b/decus/vax87a/bbs/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..e5ef0823279efaf541f3ce675e31b1c074384297
Binary files /dev/null and b/decus/vax87a/bbs/bulletin3.for differ
diff --git a/decus/vax87a/bbs/bulletin4.for b/decus/vax87a/bbs/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..18722bfbd6ef89653c5ee451148d1de7838286b1
Binary files /dev/null and b/decus/vax87a/bbs/bulletin4.for differ
diff --git a/decus/vax87a/bbs/bulletin5.for b/decus/vax87a/bbs/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..4602f9b4ea7f70d099a99b283e8f48f72f71d15f
Binary files /dev/null and b/decus/vax87a/bbs/bulletin5.for differ
diff --git a/decus/vax87a/bbs/bulletin6.for b/decus/vax87a/bbs/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..77b624a2f44c0befd59dc3e29db5d7a75f0e151e
Binary files /dev/null and b/decus/vax87a/bbs/bulletin6.for differ
diff --git a/decus/vax87a/bbs/bulletinv2.doc b/decus/vax87a/bbs/bulletinv2.doc
new file mode 100755
index 0000000000000000000000000000000000000000..896275fa22a70b6b81483678a2c262ecc727b65a
Binary files /dev/null and b/decus/vax87a/bbs/bulletinv2.doc differ
diff --git a/decus/vax87a/bullv4_0/bulletin.c b/decus/vax87a/bullv4_0/bulletin.c
new file mode 100755
index 0000000000000000000000000000000000000000..0396052059b312b88083a01dec65ec11101586f8
Binary files /dev/null and b/decus/vax87a/bullv4_0/bulletin.c differ
diff --git a/decus/vax87a/bullv4_0/bulletin.cld b/decus/vax87a/bullv4_0/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..d7ac3ba3cc65c5f816f69f2ce29f59ab729c8ab8
Binary files /dev/null and b/decus/vax87a/bullv4_0/bulletin.cld differ
diff --git a/decus/vax87a/bullv4_0/bulletin.hlb b/decus/vax87a/bullv4_0/bulletin.hlb
new file mode 100755
index 0000000000000000000000000000000000000000..e322666283b68ab844b88dc9867872192d81ae79
Binary files /dev/null and b/decus/vax87a/bullv4_0/bulletin.hlb differ
diff --git a/decus/vax87a/bullv4_0/bulletin.hlp b/decus/vax87a/bullv4_0/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..f90123908b0d4351147e7545d0a2199c8a6204e8
Binary files /dev/null and b/decus/vax87a/bullv4_0/bulletin.hlp differ
diff --git a/decus/vax87a/bullv4_0/bulletin.rnh b/decus/vax87a/bullv4_0/bulletin.rnh
new file mode 100755
index 0000000000000000000000000000000000000000..df8f6a21d4e161fa8b69aa915336894416bd19a2
Binary files /dev/null and b/decus/vax87a/bullv4_0/bulletin.rnh differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin.for b/decus/vax87d/rcaf87/netnew/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..1d216af55a602b07b00143d362b7e9be4e349a87
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin.txt b/decus/vax87d/rcaf87/netnew/bulletin.txt
new file mode 100755
index 0000000000000000000000000000000000000000..faebc43c4a0f6d31e4807c4f1bd6268f5892ee84
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin.txt differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin0.for b/decus/vax87d/rcaf87/netnew/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..c38c7d3b417172795a5f1e392891e8aed287d152
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin0.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin1.for b/decus/vax87d/rcaf87/netnew/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..4cabea2fdc7e32cd30b67a707f3ae47e0db4e1eb
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin1.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin2.for b/decus/vax87d/rcaf87/netnew/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..cf2085c1b039e5934a3aaae0bcf0b55219d538ec
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin2.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin3.for b/decus/vax87d/rcaf87/netnew/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..9408582448d48b38e32f97043764163a53906f82
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin3.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin4.for b/decus/vax87d/rcaf87/netnew/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..3fc7529d4aedcc8ba072b610746f8b840f6834e8
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin4.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin5.for b/decus/vax87d/rcaf87/netnew/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..9d9141b474f7de6ee62ba74683ab04163929fd68
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin5.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletin6.for b/decus/vax87d/rcaf87/netnew/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..3f70b1a4e94495c01a633d87731f1ce6d0b424dc
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletin6.for differ
diff --git a/decus/vax87d/rcaf87/netnew/bulletinann.txt b/decus/vax87d/rcaf87/netnew/bulletinann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..7289d1a40bc02710259ae48817b10395aad39404
Binary files /dev/null and b/decus/vax87d/rcaf87/netnew/bulletinann.txt differ
diff --git a/decus/vax88a2/nieland/bulletin/aaareadme.1st b/decus/vax88a2/nieland/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..3a546f6d3ebc24f3dc3dd25b211bedcdcfa8fae5
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/aaareadme.1st differ
diff --git a/decus/vax88a2/nieland/bulletin/allmacs.mar b/decus/vax88a2/nieland/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..afeb42f16b8e0ba1ac60da65fc6f5f5e71c8d67a
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/allmacs.mar differ
diff --git a/decus/vax88a2/nieland/bulletin/board_digest.com b/decus/vax88a2/nieland/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/board_digest.com differ
diff --git a/decus/vax88a2/nieland/bulletin/board_special.com b/decus/vax88a2/nieland/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..a25eeef17f16f1c0c0f75b4433b80c9004783762
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/board_special.com differ
diff --git a/decus/vax88a2/nieland/bulletin/bull_command.com b/decus/vax88a2/nieland/bulletin/bull_command.com
new file mode 100755
index 0000000000000000000000000000000000000000..4ce40987612597bad19470894dc71f696f3723f3
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bull_command.com differ
diff --git a/decus/vax88a2/nieland/bulletin/bullcom.cld b/decus/vax88a2/nieland/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..49bea1b195d97b2b39ddd153b92bc59f5f4ee71d
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullcom.cld differ
diff --git a/decus/vax88a2/nieland/bulletin/bullcoms1.hlp b/decus/vax88a2/nieland/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..f9d1e3d7da6309bdc9b700214ac47ded9518ba40
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax88a2/nieland/bulletin/bullcoms2.hlp b/decus/vax88a2/nieland/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..b9e5d09fc0228274461c2b6a010bcacbb291c6d6
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax88a2/nieland/bulletin/bulldir.inc b/decus/vax88a2/nieland/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..5ad1209d3cd852d0dd2dee1db689959bfebfe5c5
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulldir.inc differ
diff --git a/decus/vax88a2/nieland/bulletin/bullet1.com b/decus/vax88a2/nieland/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..e3a78cdbf0fd556ff30f13df85af3366adcf0007
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullet1.com differ
diff --git a/decus/vax88a2/nieland/bulletin/bullet2.com b/decus/vax88a2/nieland/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..d8cc25282cea24cee180b155e2d388a27b0a0f71
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullet2.com differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin.com b/decus/vax88a2/nieland/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin.com differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin.for b/decus/vax88a2/nieland/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..2fcad3bf549cde82d9d1c0f4f81442bd480dd93b
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin.hlp b/decus/vax88a2/nieland/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..e613305be0b9b9c9bc439d6f727d78bc59742bf5
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin.hlp differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin.lnk b/decus/vax88a2/nieland/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..52e1d43a8bed5bf2da6360c12d9ab1a3eb5de146
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin.lnk differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin0.for b/decus/vax88a2/nieland/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..0b3d537527dfeffe4aca3cebbd2ebcba83be5d01
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin0.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin1.for b/decus/vax88a2/nieland/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..ea2e4344598ebabc88b7cdb318c7e013450dea46
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin1.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin2.for b/decus/vax88a2/nieland/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..4c5cf2ed2f6fb163006588913a2ce029f05c9a2d
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin2.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin3.for b/decus/vax88a2/nieland/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..9d0a587df60e1b4b770df1e9b723d565f419f407
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin3.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin4.for b/decus/vax88a2/nieland/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..df8b99ddd2a44694281672cae2122ae6c5d90700
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin4.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin5.for b/decus/vax88a2/nieland/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..1f5cc707b83e52ab73e4ea8881aad41a032413c4
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin5.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin6.for b/decus/vax88a2/nieland/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..ba3ef64697c66026bf2f7969338e1beb5ae499e2
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin6.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin7.for b/decus/vax88a2/nieland/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..18e24cb1dc3aa44654760caaa40157e93ca387ed
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin7.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bulletin8.for b/decus/vax88a2/nieland/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..e4225057d02bf7dfb6eee1348db30bfeea59251d
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulletin8.for differ
diff --git a/decus/vax88a2/nieland/bulletin/bullfiles.inc b/decus/vax88a2/nieland/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..de819fac0f18c3193709bee85623a6c8c12955c2
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullfiles.inc differ
diff --git a/decus/vax88a2/nieland/bulletin/bullfolder.inc b/decus/vax88a2/nieland/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..088b8c168c4587cd95aefa0b52460ab9148031ee
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullfolder.inc differ
diff --git a/decus/vax88a2/nieland/bulletin/bullmain.cld b/decus/vax88a2/nieland/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..b886f368597b7180e06a94401b4d8dbae106883e
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullmain.cld differ
diff --git a/decus/vax88a2/nieland/bulletin/bullstart.com b/decus/vax88a2/nieland/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..8c2bfd395f649713883bcb9e1f1389cf3d7905f1
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bullstart.com differ
diff --git a/decus/vax88a2/nieland/bulletin/bulluser.inc b/decus/vax88a2/nieland/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..cae809f773f635c910a35ad722532f12079a69fc
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/bulluser.inc differ
diff --git a/decus/vax88a2/nieland/bulletin/create.com b/decus/vax88a2/nieland/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..daf156a36ef27a550218ed69b9ed51e7e40528f0
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/create.com differ
diff --git a/decus/vax88a2/nieland/bulletin/handout.txt b/decus/vax88a2/nieland/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/handout.txt differ
diff --git a/decus/vax88a2/nieland/bulletin/help.com b/decus/vax88a2/nieland/bulletin/help.com
new file mode 100755
index 0000000000000000000000000000000000000000..b2c75bfbb0b3a0aa781b41556a2c7a42732d641c
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/help.com differ
diff --git a/decus/vax88a2/nieland/bulletin/install.com b/decus/vax88a2/nieland/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..3a7104abb31541800e5dd74cb93ac67751ba4a70
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/install.com differ
diff --git a/decus/vax88a2/nieland/bulletin/instruct.com b/decus/vax88a2/nieland/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/instruct.com differ
diff --git a/decus/vax88a2/nieland/bulletin/instruct.txt b/decus/vax88a2/nieland/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/instruct.txt differ
diff --git a/decus/vax88a2/nieland/bulletin/login.com b/decus/vax88a2/nieland/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..ce8031e0e94fa312b86752970b9d38a1a9ef027d
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/login.com differ
diff --git a/decus/vax88a2/nieland/bulletin/makefile b/decus/vax88a2/nieland/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..2c6ae242f846c5e0925254b162e5907142a39126
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/makefile differ
diff --git a/decus/vax88a2/nieland/bulletin/nonsystem.txt b/decus/vax88a2/nieland/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/vax88a2/nieland/bulletin/nonsystem.txt differ
diff --git a/decus/vax88a2/nieland/manual/bulletin.tex b/decus/vax88a2/nieland/manual/bulletin.tex
new file mode 100755
index 0000000000000000000000000000000000000000..b6ab6b4674b7cec014b5008d0b7f665d8bd312a4
Binary files /dev/null and b/decus/vax88a2/nieland/manual/bulletin.tex differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin.for b/decus/vax88a3/rcas88/nets88/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..44c3218ee26dec599895404df018b638b875ed39
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin0.for b/decus/vax88a3/rcas88/nets88/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..6a66d13ff21b852126fa01a3d277b1c25f29cd75
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin0.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin1.for b/decus/vax88a3/rcas88/nets88/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..4402414a52b15d78d56bedeeede38e32f164a353
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin1.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin3.for b/decus/vax88a3/rcas88/nets88/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..7f8148f49e5e79737c17d555dfe98e69793de1f2
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin3.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin4.for b/decus/vax88a3/rcas88/nets88/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..9906335b06f6592b78813469c22c3f488d12e8b8
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin4.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin5.for b/decus/vax88a3/rcas88/nets88/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..ae9155b5c7522d74f275fbeac5fe2f991e205d0f
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin5.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin6.for b/decus/vax88a3/rcas88/nets88/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..a79553ae8e1ddcbbb49a66159ff0818ab106c521
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin6.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin7.for b/decus/vax88a3/rcas88/nets88/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..956b72f76655f209db8997e105ec630a364d71de
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin7.for differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletin7bugbug.txt b/decus/vax88a3/rcas88/nets88/bulletin7bugbug.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8715d8f37b594e176d310611b5c6dc1027753d34
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletin7bugbug.txt differ
diff --git a/decus/vax88a3/rcas88/nets88/bulletinann.txt b/decus/vax88a3/rcas88/nets88/bulletinann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..b627a2f9294c327c864b50f46eaa96957f33a1f3
Binary files /dev/null and b/decus/vax88a3/rcas88/nets88/bulletinann.txt differ
diff --git a/decus/vax88b1/nieland/bulletin/aaareadme.1st b/decus/vax88b1/nieland/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..bf65c7ef1c7db4ccc289b6c3eee814c74b7c5a5f
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/aaareadme.1st differ
diff --git a/decus/vax88b1/nieland/bulletin/allmacs.mar b/decus/vax88b1/nieland/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..db899a4bfc17e3dd9d4a9e303a7b70e1b61fefa4
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/allmacs.mar differ
diff --git a/decus/vax88b1/nieland/bulletin/board_digest.com b/decus/vax88b1/nieland/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/board_digest.com differ
diff --git a/decus/vax88b1/nieland/bulletin/board_special.com b/decus/vax88b1/nieland/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..a25eeef17f16f1c0c0f75b4433b80c9004783762
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/board_special.com differ
diff --git a/decus/vax88b1/nieland/bulletin/bullcom.cld b/decus/vax88b1/nieland/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..88bb40db53063288bd0217ba6132ccfe80fc9e81
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullcom.cld differ
diff --git a/decus/vax88b1/nieland/bulletin/bullcoms1.hlp b/decus/vax88b1/nieland/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..a5e3e2c5dff842f1f00b582a4d820b67e4d67fc1
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax88b1/nieland/bulletin/bullcoms2.hlp b/decus/vax88b1/nieland/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..69f93dee35f80088edbb26b4baf45700735dbc61
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax88b1/nieland/bulletin/bulldir.inc b/decus/vax88b1/nieland/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..5d5024aab029b724fd07915af10589050e2c993f
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulldir.inc differ
diff --git a/decus/vax88b1/nieland/bulletin/bullet1.com b/decus/vax88b1/nieland/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..6101a8a8fb27e05c1393c50545d569289edbae8c
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullet1.com differ
diff --git a/decus/vax88b1/nieland/bulletin/bullet2.com b/decus/vax88b1/nieland/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..ee0b696b53867cfcdbdc1dd97ab26f190d585544
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullet2.com differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.cld b/decus/vax88b1/nieland/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..3d4cd04a0c7d5d63c5f37cc370e738bdd732a672
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.cld differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.com b/decus/vax88b1/nieland/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.com differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.for b/decus/vax88b1/nieland/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..7b8d0dff27c37aa4718b42b05b3b08da144efca8
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.hlp b/decus/vax88b1/nieland/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..2d590a6cbe0289b30f7a801351d9e6caba2375b3
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.hlp differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.lnk b/decus/vax88b1/nieland/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..4ce1f464a04800634f10af2997076237e7d1d079
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.lnk differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.message b/decus/vax88b1/nieland/bulletin/bulletin.message
new file mode 100755
index 0000000000000000000000000000000000000000..44c7871cfdb088fb903f63997de9a8b0d2fe4eff
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.message differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.message2 b/decus/vax88b1/nieland/bulletin/bulletin.message2
new file mode 100755
index 0000000000000000000000000000000000000000..6a7f5327e288f48b400689ddd5605435f03540d9
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.message2 differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin.message3 b/decus/vax88b1/nieland/bulletin/bulletin.message3
new file mode 100755
index 0000000000000000000000000000000000000000..edeafc2f27db395749080f9e0f79f875c74cdaf2
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin.message3 differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin0.for b/decus/vax88b1/nieland/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..2a39b36a6204427abebe1bcf1153848db36ee9c3
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin0.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin1.for b/decus/vax88b1/nieland/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..9802d24ca9a1d7f266e3fce475ef91ea9f69457c
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin1.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin2.for b/decus/vax88b1/nieland/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..0e61bec87adc4639a6070804808f0a55e5b9de7d
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin2.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin3.for b/decus/vax88b1/nieland/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..5c48c74ec52d064d6d1595ce7d28822c3374814b
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin3.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin4.for b/decus/vax88b1/nieland/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..be1730aa2d1f3d2299ecaada8fca9e591240c0ca
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin4.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin5.for b/decus/vax88b1/nieland/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..485a7670cb4630d00a083b6fd448164832437c12
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin5.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin6.for b/decus/vax88b1/nieland/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..89467354fbb995114283df364ce52a24dc40ace5
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin6.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin7.for b/decus/vax88b1/nieland/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..87c847e517a278e7cebbb269a3d5aac5f5a79038
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin7.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin8.for b/decus/vax88b1/nieland/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..2795d04d86a2a597694f1dc8e49e50a052d505a9
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin8.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bulletin9.for b/decus/vax88b1/nieland/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..0bc8808952b132a6e621bedc3a922f252881d869
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulletin9.for differ
diff --git a/decus/vax88b1/nieland/bulletin/bullfiles.inc b/decus/vax88b1/nieland/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..de819fac0f18c3193709bee85623a6c8c12955c2
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullfiles.inc differ
diff --git a/decus/vax88b1/nieland/bulletin/bullfolder.inc b/decus/vax88b1/nieland/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..0ca16cfb508195b03dff2b9fa99c8fb0fc6b8392
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullfolder.inc differ
diff --git a/decus/vax88b1/nieland/bulletin/bullmain.cld b/decus/vax88b1/nieland/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..1c03449771a68936eb9a6064fa8e3859fac1ecb5
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullmain.cld differ
diff --git a/decus/vax88b1/nieland/bulletin/bullstart.com b/decus/vax88b1/nieland/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..276e3da48b5e9542f37408301544a06e10b2890a
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bullstart.com differ
diff --git a/decus/vax88b1/nieland/bulletin/bulluser.inc b/decus/vax88b1/nieland/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..cae809f773f635c910a35ad722532f12079a69fc
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/bulluser.inc differ
diff --git a/decus/vax88b1/nieland/bulletin/create.com b/decus/vax88b1/nieland/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..51ffa8a9d5170d90021cb5438406e4c48d20b8cf
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/create.com differ
diff --git a/decus/vax88b1/nieland/bulletin/dclremote.com b/decus/vax88b1/nieland/bulletin/dclremote.com
new file mode 100755
index 0000000000000000000000000000000000000000..2c8b5ba8e1f1d24135d8f62e8977667d0ab5ff68
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/dclremote.com differ
diff --git a/decus/vax88b1/nieland/bulletin/handout.txt b/decus/vax88b1/nieland/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/handout.txt differ
diff --git a/decus/vax88b1/nieland/bulletin/install.com b/decus/vax88b1/nieland/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..216570d27ffa0574f2c708308f83da6a12ae0eff
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/install.com differ
diff --git a/decus/vax88b1/nieland/bulletin/install_remote.com b/decus/vax88b1/nieland/bulletin/install_remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..51868b764296f6fcd993327faee1b09c096a77db
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/install_remote.com differ
diff --git a/decus/vax88b1/nieland/bulletin/instruct.com b/decus/vax88b1/nieland/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/instruct.com differ
diff --git a/decus/vax88b1/nieland/bulletin/instruct.txt b/decus/vax88b1/nieland/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/instruct.txt differ
diff --git a/decus/vax88b1/nieland/bulletin/login.com b/decus/vax88b1/nieland/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..51f4aa686de04b0f52a3942453a416e589d90177
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/login.com differ
diff --git a/decus/vax88b1/nieland/bulletin/makefile b/decus/vax88b1/nieland/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..1d00e48d54e22bf08ee6e7a81489d955c149a0c3
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/makefile differ
diff --git a/decus/vax88b1/nieland/bulletin/nonsystem.txt b/decus/vax88b1/nieland/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/nonsystem.txt differ
diff --git a/decus/vax88b1/nieland/bulletin/remote.com b/decus/vax88b1/nieland/bulletin/remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..5cc6fbf88780364f4639e3581d10bf442e7dc58e
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/remote.com differ
diff --git a/decus/vax88b1/nieland/bulletin/v5/aaareadme.1st b/decus/vax88b1/nieland/bulletin/v5/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..b6a03297df494369ed01e34b5db4e14dc13da819
Binary files /dev/null and b/decus/vax88b1/nieland/bulletin/v5/aaareadme.1st differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin.bwr b/decus/vax88b5/rcaf88/netf88/bulletin.bwr
new file mode 100755
index 0000000000000000000000000000000000000000..62b9668d936f97bd086737ab641e1f739f584453
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin.bwr differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin.for b/decus/vax88b5/rcaf88/netf88/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..2c99e753f4658fc074cb9bcbcf722955de2138a2
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin0.for b/decus/vax88b5/rcaf88/netf88/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..2f51ad7d4749edfcaa72f0f201d3f5c196f13f53
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin0.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin1.for b/decus/vax88b5/rcaf88/netf88/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..622e8ffab27c006e384346edbb717e8105f9bd68
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin1.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin2.for b/decus/vax88b5/rcaf88/netf88/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..dd00e6f32803fdd6506d3596cacb39482f2bb0b1
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin2.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin3.for b/decus/vax88b5/rcaf88/netf88/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..5d6220dedf41b06cb60e13adf6243b5e636d2dda
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin3.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin4.for b/decus/vax88b5/rcaf88/netf88/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..7810289b450f7355a63f62844af079ad87c70dfb
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin4.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin5.for b/decus/vax88b5/rcaf88/netf88/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..9ef6966ce6fd204d25fc0b8a978d247d473eec47
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin5.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin6.for b/decus/vax88b5/rcaf88/netf88/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..e0919a80003d87ac9508b094843f7ed1099cca7b
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin6.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin7.for b/decus/vax88b5/rcaf88/netf88/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..0460801eb92625aeecb5f84b1e74bd9f4ed207c1
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin7.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin8.for b/decus/vax88b5/rcaf88/netf88/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..450de8fc76c7ca8e86ad6389cb8c9dc58def08f4
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin8.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin9.for b/decus/vax88b5/rcaf88/netf88/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..b3161af108fd49dadf69ba352757358f4f00426e
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin9.for differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin_ann.txt b/decus/vax88b5/rcaf88/netf88/bulletin_ann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..f3601d202bfc76d9ec47fd4b75b9381b4ab7fac0
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin_ann.txt differ
diff --git a/decus/vax88b5/rcaf88/netf88/bulletin_warning_vms_v5.txt b/decus/vax88b5/rcaf88/netf88/bulletin_warning_vms_v5.txt
new file mode 100755
index 0000000000000000000000000000000000000000..939893a2ed8025760c8fa4358ed11eeb7d7fb87f
Binary files /dev/null and b/decus/vax88b5/rcaf88/netf88/bulletin_warning_vms_v5.txt differ
diff --git a/decus/vax89a2/nieland/bulletin/aaareadme.1st b/decus/vax89a2/nieland/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..407fe5e45d4ad818080f69f8c5db18f1ab9ff596
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/aaareadme.1st differ
diff --git a/decus/vax89a2/nieland/bulletin/aaareadme.too b/decus/vax89a2/nieland/bulletin/aaareadme.too
new file mode 100755
index 0000000000000000000000000000000000000000..f2e43eddf808620e41b4df7f76b0146f18bdd0c2
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/aaareadme.too differ
diff --git a/decus/vax89a2/nieland/bulletin/allmacs.mar b/decus/vax89a2/nieland/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..4e65d4a20aced986b1c58134afc7b18f5e72a569
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/allmacs.mar differ
diff --git a/decus/vax89a2/nieland/bulletin/board_digest.com b/decus/vax89a2/nieland/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..2526a71190eab00c02b8037c1f59f3ecb59f6565
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/board_digest.com differ
diff --git a/decus/vax89a2/nieland/bulletin/board_special.com b/decus/vax89a2/nieland/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..b378180e783ed2c7dae2e85056a8a3bb1b8beac9
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/board_special.com differ
diff --git a/decus/vax89a2/nieland/bulletin/bullcom.cld b/decus/vax89a2/nieland/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..9bd44b7d8f12e8ddc13131a7038509009933958f
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bullcom.cld differ
diff --git a/decus/vax89a2/nieland/bulletin/bullcoms1.hlp b/decus/vax89a2/nieland/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..0baba735ab7fdab8672d02df3bf22149f2299004
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax89a2/nieland/bulletin/bullcoms2.hlp b/decus/vax89a2/nieland/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..6fed647e7b66b4ce74c7c455aaa562e58d8976cd
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax89a2/nieland/bulletin/bulletin.cld b/decus/vax89a2/nieland/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..f95c82a62d741fff03c1a7219c88c91edcb318f5
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bulletin.cld differ
diff --git a/decus/vax89a2/nieland/bulletin/bulletin.com b/decus/vax89a2/nieland/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bulletin.com differ
diff --git a/decus/vax89a2/nieland/bulletin/bulletin.hlp b/decus/vax89a2/nieland/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..2d590a6cbe0289b30f7a801351d9e6caba2375b3
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bulletin.hlp differ
diff --git a/decus/vax89a2/nieland/bulletin/bulletin.lnk b/decus/vax89a2/nieland/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..7af21b8ab07fa25e446c1861bbac6823b6f56653
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bulletin.lnk differ
diff --git a/decus/vax89a2/nieland/bulletin/bullmain.cld b/decus/vax89a2/nieland/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..ad1e11e19717613eece72e9e31e459ef69fc770a
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bullmain.cld differ
diff --git a/decus/vax89a2/nieland/bulletin/bullstart.com b/decus/vax89a2/nieland/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/bullstart.com differ
diff --git a/decus/vax89a2/nieland/bulletin/create.com b/decus/vax89a2/nieland/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..4c06d32b76dbf8d3db5a3e967da9b77c0011d876
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/create.com differ
diff --git a/decus/vax89a2/nieland/bulletin/createrest.com b/decus/vax89a2/nieland/bulletin/createrest.com
new file mode 100755
index 0000000000000000000000000000000000000000..f1955432c283b1e01852e098a67d2e1e3574aff6
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/createrest.com differ
diff --git a/decus/vax89a2/nieland/bulletin/dclremote.com b/decus/vax89a2/nieland/bulletin/dclremote.com
new file mode 100755
index 0000000000000000000000000000000000000000..366a7cb20f0345ced7f35923d5213e5d55b8e85c
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/dclremote.com differ
diff --git a/decus/vax89a2/nieland/bulletin/handout.txt b/decus/vax89a2/nieland/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/handout.txt differ
diff --git a/decus/vax89a2/nieland/bulletin/install.com b/decus/vax89a2/nieland/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..1bbbe6b2ab16e30c8fb4e6f63b6e49479eb8868b
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/install.com differ
diff --git a/decus/vax89a2/nieland/bulletin/install_remote.com b/decus/vax89a2/nieland/bulletin/install_remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..f9ee8ae3e378f5d9adc75741675c41cf5c502576
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/install_remote.com differ
diff --git a/decus/vax89a2/nieland/bulletin/instruct.com b/decus/vax89a2/nieland/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/instruct.com differ
diff --git a/decus/vax89a2/nieland/bulletin/instruct.txt b/decus/vax89a2/nieland/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/instruct.txt differ
diff --git a/decus/vax89a2/nieland/bulletin/login.com b/decus/vax89a2/nieland/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..d8fc0a2bbfa96bc6ddf5163ccd516b6edd22f967
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/login.com differ
diff --git a/decus/vax89a2/nieland/bulletin/makefile b/decus/vax89a2/nieland/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..af170faa1cec9fba058124441782750ff8473514
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/makefile differ
diff --git a/decus/vax89a2/nieland/bulletin/nonsystem.txt b/decus/vax89a2/nieland/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/nonsystem.txt differ
diff --git a/decus/vax89a2/nieland/bulletin/pmdf.com b/decus/vax89a2/nieland/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..024f934c186308a4cf3a94d20cf86ecad8662e91
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/pmdf.com differ
diff --git a/decus/vax89a2/nieland/bulletin/remote.com b/decus/vax89a2/nieland/bulletin/remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..34c381151b3fd5eeb58f1981a37d659bbba469e3
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/remote.com differ
diff --git a/decus/vax89a2/nieland/bulletin/writemsg.txt b/decus/vax89a2/nieland/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..3cbce235b2a28116089a8d549d6800306fc5569c
Binary files /dev/null and b/decus/vax89a2/nieland/bulletin/writemsg.txt differ
diff --git a/decus/vax90a/bulletin/aaa-readme.net-txt b/decus/vax90a/bulletin/aaa-readme.net-txt
new file mode 100755
index 0000000000000000000000000000000000000000..2c55b6da10da049c0149b1406abc1abc45cb9ed7
Binary files /dev/null and b/decus/vax90a/bulletin/aaa-readme.net-txt differ
diff --git a/decus/vax90a/bulletin/aaareadme.1st b/decus/vax90a/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..5a7bb0862b05c2011bc67da9206784fbb8f032cd
Binary files /dev/null and b/decus/vax90a/bulletin/aaareadme.1st differ
diff --git a/decus/vax90a/bulletin/aaareadme.txt b/decus/vax90a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..68a7caa62230deac8ca2f71a188571894d26cbe9
Binary files /dev/null and b/decus/vax90a/bulletin/aaareadme.txt differ
diff --git a/decus/vax90a/bulletin/board_digest.com b/decus/vax90a/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/vax90a/bulletin/board_digest.com differ
diff --git a/decus/vax90a/bulletin/board_special.com b/decus/vax90a/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6ff014483565e3b6f13a05e42ba24b8178f9da3
Binary files /dev/null and b/decus/vax90a/bulletin/board_special.com differ
diff --git a/decus/vax90a/bulletin/bullcoms1.hlp b/decus/vax90a/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..3c5b33f681cb6b97265f379b437da625ceca9d3e
Binary files /dev/null and b/decus/vax90a/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax90a/bulletin/bullcoms2.hlp b/decus/vax90a/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..d2c51e44501bbcb4fea58a35efc6ba34ee3fd317
Binary files /dev/null and b/decus/vax90a/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax90a/bulletin/bulldir.inc b/decus/vax90a/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..f874a3abbbe8921b74a4acfe5bfaa47f69ed96a7
Binary files /dev/null and b/decus/vax90a/bulletin/bulldir.inc differ
diff --git a/decus/vax90a/bulletin/bullet1.com b/decus/vax90a/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..8e26c26451177dc2e802d490dfdf615463e79164
Binary files /dev/null and b/decus/vax90a/bulletin/bullet1.com differ
diff --git a/decus/vax90a/bulletin/bullet2.com b/decus/vax90a/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..e95782006eb42f732055ca195266f7d2f1e35b12
Binary files /dev/null and b/decus/vax90a/bulletin/bullet2.com differ
diff --git a/decus/vax90a/bulletin/bulletin.cld b/decus/vax90a/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..93d3d16ef7ce0323dff6533dee70f5111caf79fc
Binary files /dev/null and b/decus/vax90a/bulletin/bulletin.cld differ
diff --git a/decus/vax90a/bulletin/bulletin.com b/decus/vax90a/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vax90a/bulletin/bulletin.com differ
diff --git a/decus/vax90a/bulletin/bulletin.hlp b/decus/vax90a/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..2d590a6cbe0289b30f7a801351d9e6caba2375b3
Binary files /dev/null and b/decus/vax90a/bulletin/bulletin.hlp differ
diff --git a/decus/vax90a/bulletin/bulletin.lnk b/decus/vax90a/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..71ee6a64a65dad08f984daf6f6e4972eae7ccf34
Binary files /dev/null and b/decus/vax90a/bulletin/bulletin.lnk differ
diff --git a/decus/vax90a/bulletin/bulletin_wheretoget.txt b/decus/vax90a/bulletin/bulletin_wheretoget.txt
new file mode 100755
index 0000000000000000000000000000000000000000..b9b02c46f5ed41fb893efc9c069be3ce438f268d
Binary files /dev/null and b/decus/vax90a/bulletin/bulletin_wheretoget.txt differ
diff --git a/decus/vax90a/bulletin/bullfiles.inc b/decus/vax90a/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..07903a781e0f7593c32241422fa169876a5af842
Binary files /dev/null and b/decus/vax90a/bulletin/bullfiles.inc differ
diff --git a/decus/vax90a/bulletin/bullfolder.inc b/decus/vax90a/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..0ca16cfb508195b03dff2b9fa99c8fb0fc6b8392
Binary files /dev/null and b/decus/vax90a/bulletin/bullfolder.inc differ
diff --git a/decus/vax90a/bulletin/bullstart.com b/decus/vax90a/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/vax90a/bulletin/bullstart.com differ
diff --git a/decus/vax90a/bulletin/bulluser.inc b/decus/vax90a/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..6e97e2612a9f908b0808e2a4c451527621d84cdb
Binary files /dev/null and b/decus/vax90a/bulletin/bulluser.inc differ
diff --git a/decus/vax90a/bulletin/create.com b/decus/vax90a/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..3e3c722b40ccf8ff1c10c3d6338839eace5d63e9
Binary files /dev/null and b/decus/vax90a/bulletin/create.com differ
diff --git a/decus/vax90a/bulletin/dclremote.com b/decus/vax90a/bulletin/dclremote.com
new file mode 100755
index 0000000000000000000000000000000000000000..2c8b5ba8e1f1d24135d8f62e8977667d0ab5ff68
Binary files /dev/null and b/decus/vax90a/bulletin/dclremote.com differ
diff --git a/decus/vax90a/bulletin/handout.txt b/decus/vax90a/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vax90a/bulletin/handout.txt differ
diff --git a/decus/vax90a/bulletin/install.com b/decus/vax90a/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..a94bca0bb58982626705b4e6208eec9863702ce0
Binary files /dev/null and b/decus/vax90a/bulletin/install.com differ
diff --git a/decus/vax90a/bulletin/install_remote.com b/decus/vax90a/bulletin/install_remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..93ae3b1bb784e75b1617e2af2b092bfa1cae07ef
Binary files /dev/null and b/decus/vax90a/bulletin/install_remote.com differ
diff --git a/decus/vax90a/bulletin/instruct.com b/decus/vax90a/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/vax90a/bulletin/instruct.com differ
diff --git a/decus/vax90a/bulletin/instruct.txt b/decus/vax90a/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vax90a/bulletin/instruct.txt differ
diff --git a/decus/vax90a/bulletin/login.com b/decus/vax90a/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..db86b1d3c4c892235d5c896df3d265f7887f214a
Binary files /dev/null and b/decus/vax90a/bulletin/login.com differ
diff --git a/decus/vax90a/bulletin/makefile b/decus/vax90a/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..9736a5b07f8ff41953e9eeb2811cff051e88342c
Binary files /dev/null and b/decus/vax90a/bulletin/makefile differ
diff --git a/decus/vax90a/bulletin/nonsystem.txt b/decus/vax90a/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/vax90a/bulletin/nonsystem.txt differ
diff --git a/decus/vax90a/bulletin/pmdf.com b/decus/vax90a/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..e325be3d6e9957a3250b6c1188fb9dcb4b44c015
Binary files /dev/null and b/decus/vax90a/bulletin/pmdf.com differ
diff --git a/decus/vax90a/bulletin/remote.com b/decus/vax90a/bulletin/remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..5cc6fbf88780364f4639e3581d10bf442e7dc58e
Binary files /dev/null and b/decus/vax90a/bulletin/remote.com differ
diff --git a/decus/vax90a/bulletin/writemsg.txt b/decus/vax90a/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6ee4ec02e151fc32828c4e890830eee127cf5da3
Binary files /dev/null and b/decus/vax90a/bulletin/writemsg.txt differ
diff --git a/decus/vax90b1/bulletin/aaareadme.1st b/decus/vax90b1/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..cf59279e6c839fb8e829b7b0d42fbaea3ce2fa32
Binary files /dev/null and b/decus/vax90b1/bulletin/aaareadme.1st differ
diff --git a/decus/vax90b1/bulletin/aaareadme.txt b/decus/vax90b1/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..69b58d2fb84f1d24555d1d3dc49c7487ccbca78e
Binary files /dev/null and b/decus/vax90b1/bulletin/aaareadme.txt differ
diff --git a/decus/vax90b1/bulletin/announce.txt b/decus/vax90b1/bulletin/announce.txt
new file mode 100755
index 0000000000000000000000000000000000000000..fd6778a94efabbcada7a5c915cf946f3ac53e790
Binary files /dev/null and b/decus/vax90b1/bulletin/announce.txt differ
diff --git a/decus/vax90b1/bulletin/board_digest.com b/decus/vax90b1/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/vax90b1/bulletin/board_digest.com differ
diff --git a/decus/vax90b1/bulletin/board_special.com b/decus/vax90b1/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6ff014483565e3b6f13a05e42ba24b8178f9da3
Binary files /dev/null and b/decus/vax90b1/bulletin/board_special.com differ
diff --git a/decus/vax90b1/bulletin/bullcom.cld b/decus/vax90b1/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..1f9aca5e3a68d1fd4946ebbf231c3219ee1aeaf6
Binary files /dev/null and b/decus/vax90b1/bulletin/bullcom.cld differ
diff --git a/decus/vax90b1/bulletin/bullcoms1.hlp b/decus/vax90b1/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..d4a571ebff7514b27da1d596b05abd447af47134
Binary files /dev/null and b/decus/vax90b1/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax90b1/bulletin/bullcoms2.hlp b/decus/vax90b1/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..01d8bae47f5917a898d3dad26a6694ba457e5c04
Binary files /dev/null and b/decus/vax90b1/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax90b1/bulletin/bulletin.cld b/decus/vax90b1/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..45e23e07652f10306862bd28010d6602b1c0a965
Binary files /dev/null and b/decus/vax90b1/bulletin/bulletin.cld differ
diff --git a/decus/vax90b1/bulletin/bulletin.com b/decus/vax90b1/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vax90b1/bulletin/bulletin.com differ
diff --git a/decus/vax90b1/bulletin/bulletin.hlp b/decus/vax90b1/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..b5da9bd48fc3cfe62e5f32400fa3ef2bcbd4abbc
Binary files /dev/null and b/decus/vax90b1/bulletin/bulletin.hlp differ
diff --git a/decus/vax90b1/bulletin/bulletin.lnk b/decus/vax90b1/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..c0f6cff8955fa9e6cb02a9f15bce357ec1890ff0
Binary files /dev/null and b/decus/vax90b1/bulletin/bulletin.lnk differ
diff --git a/decus/vax90b1/bulletin/bulletin10.for b/decus/vax90b1/bulletin/bulletin10.for
new file mode 100755
index 0000000000000000000000000000000000000000..9200d3ef280e87e943a688955aa28cf0bcc327e6
Binary files /dev/null and b/decus/vax90b1/bulletin/bulletin10.for differ
diff --git a/decus/vax90b1/bulletin/bullmain.cld b/decus/vax90b1/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..59355d8683aa20f3584178f36c83b9d180587909
Binary files /dev/null and b/decus/vax90b1/bulletin/bullmain.cld differ
diff --git a/decus/vax90b1/bulletin/bullstart.com b/decus/vax90b1/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/vax90b1/bulletin/bullstart.com differ
diff --git a/decus/vax90b1/bulletin/create.com b/decus/vax90b1/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..2f2de9a774ea2add530b1b678fb8ca9814dd2ff5
Binary files /dev/null and b/decus/vax90b1/bulletin/create.com differ
diff --git a/decus/vax90b1/bulletin/dclremote.com b/decus/vax90b1/bulletin/dclremote.com
new file mode 100755
index 0000000000000000000000000000000000000000..2c8b5ba8e1f1d24135d8f62e8977667d0ab5ff68
Binary files /dev/null and b/decus/vax90b1/bulletin/dclremote.com differ
diff --git a/decus/vax90b1/bulletin/handout.txt b/decus/vax90b1/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vax90b1/bulletin/handout.txt differ
diff --git a/decus/vax90b1/bulletin/install.com b/decus/vax90b1/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..35680c5685788ecb15f70c7af8a641704cc8cefc
Binary files /dev/null and b/decus/vax90b1/bulletin/install.com differ
diff --git a/decus/vax90b1/bulletin/install_remote.com b/decus/vax90b1/bulletin/install_remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..93ae3b1bb784e75b1617e2af2b092bfa1cae07ef
Binary files /dev/null and b/decus/vax90b1/bulletin/install_remote.com differ
diff --git a/decus/vax90b1/bulletin/instruct.com b/decus/vax90b1/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/vax90b1/bulletin/instruct.com differ
diff --git a/decus/vax90b1/bulletin/instruct.txt b/decus/vax90b1/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vax90b1/bulletin/instruct.txt differ
diff --git a/decus/vax90b1/bulletin/login.com b/decus/vax90b1/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..db86b1d3c4c892235d5c896df3d265f7887f214a
Binary files /dev/null and b/decus/vax90b1/bulletin/login.com differ
diff --git a/decus/vax90b1/bulletin/makefile b/decus/vax90b1/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..bf1af6dddff7f9302134b65af0c696c45efdce4b
Binary files /dev/null and b/decus/vax90b1/bulletin/makefile differ
diff --git a/decus/vax90b1/bulletin/nonsystem.txt b/decus/vax90b1/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/vax90b1/bulletin/nonsystem.txt differ
diff --git a/decus/vax90b1/bulletin/pmdf.com b/decus/vax90b1/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6fcd3e71ed3b678041c58bb57cd834f9fc976e0
Binary files /dev/null and b/decus/vax90b1/bulletin/pmdf.com differ
diff --git a/decus/vax90b1/bulletin/remote.com b/decus/vax90b1/bulletin/remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..5cc6fbf88780364f4639e3581d10bf442e7dc58e
Binary files /dev/null and b/decus/vax90b1/bulletin/remote.com differ
diff --git a/decus/vax90b1/bulletin/writemsg.txt b/decus/vax90b1/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6ee4ec02e151fc32828c4e890830eee127cf5da3
Binary files /dev/null and b/decus/vax90b1/bulletin/writemsg.txt differ
diff --git a/decus/vax90b1/gce90b/bulletin_beta/bull20_ann.txt b/decus/vax90b1/gce90b/bulletin_beta/bull20_ann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..9db790eafced7d41f9acff57434c4df41f54c7f1
Binary files /dev/null and b/decus/vax90b1/gce90b/bulletin_beta/bull20_ann.txt differ
diff --git a/decus/vax90b1/gce90b/bulletin_beta/bulletin.doc b/decus/vax90b1/gce90b/bulletin_beta/bulletin.doc
new file mode 100755
index 0000000000000000000000000000000000000000..20f0ff89865f3c05d862e3e68d834177adc5dea1
Binary files /dev/null and b/decus/vax90b1/gce90b/bulletin_beta/bulletin.doc differ
diff --git a/decus/vax90b1/gce90b/bulletin_beta/bulletin_beta_ann.txt b/decus/vax90b1/gce90b/bulletin_beta/bulletin_beta_ann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..e6548f6c7682e2eb28c20b082698123c92b63284
Binary files /dev/null and b/decus/vax90b1/gce90b/bulletin_beta/bulletin_beta_ann.txt differ
diff --git a/decus/vax90b1/gce90b/net90b/bulletin_bugfix0.src b/decus/vax90b1/gce90b/net90b/bulletin_bugfix0.src
new file mode 100755
index 0000000000000000000000000000000000000000..f5666b8a0c3206029b70c0f00a92d582f4c4b512
Binary files /dev/null and b/decus/vax90b1/gce90b/net90b/bulletin_bugfix0.src differ
diff --git a/decus/vax90b1/gce90b/net90b/bulletin_bugfix1.src b/decus/vax90b1/gce90b/net90b/bulletin_bugfix1.src
new file mode 100755
index 0000000000000000000000000000000000000000..833025340b98db3b935af5f2e5634f1bd8b4085b
Binary files /dev/null and b/decus/vax90b1/gce90b/net90b/bulletin_bugfix1.src differ
diff --git a/decus/vax91a/bulletin/aaareadme.txt b/decus/vax91a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..987fa84faef5ca2c234738a6e7c4dc7c5a58f356
Binary files /dev/null and b/decus/vax91a/bulletin/aaareadme.txt differ
diff --git a/decus/vax91a/bulletin/allmacs.mar b/decus/vax91a/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..f117187630de34046ab557245d5d6d169da96919
Binary files /dev/null and b/decus/vax91a/bulletin/allmacs.mar differ
diff --git a/decus/vax91a/bulletin/board_digest.com b/decus/vax91a/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/vax91a/bulletin/board_digest.com differ
diff --git a/decus/vax91a/bulletin/board_special.com b/decus/vax91a/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6ff014483565e3b6f13a05e42ba24b8178f9da3
Binary files /dev/null and b/decus/vax91a/bulletin/board_special.com differ
diff --git a/decus/vax91a/bulletin/bull_news.c b/decus/vax91a/bulletin/bull_news.c
new file mode 100755
index 0000000000000000000000000000000000000000..a89eaf643f113791992c47192e9e8f134cff6c6d
Binary files /dev/null and b/decus/vax91a/bulletin/bull_news.c differ
diff --git a/decus/vax91a/bulletin/bull_newsdummy.for b/decus/vax91a/bulletin/bull_newsdummy.for
new file mode 100755
index 0000000000000000000000000000000000000000..2e59f10293e1089c8ffa83e729545f3139c71643
Binary files /dev/null and b/decus/vax91a/bulletin/bull_newsdummy.for differ
diff --git a/decus/vax91a/bulletin/bullcom.cld b/decus/vax91a/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..46e60331e90efb62daf5db38b42a17ca8b083d8e
Binary files /dev/null and b/decus/vax91a/bulletin/bullcom.cld differ
diff --git a/decus/vax91a/bulletin/bullcoms1.hlp b/decus/vax91a/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..5b78508141d04dd8f11ba95e5e6db16b11d7e246
Binary files /dev/null and b/decus/vax91a/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax91a/bulletin/bullcoms2.hlp b/decus/vax91a/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..1c48cc2c08b6ee1b1676ecb39d4047f2c721f297
Binary files /dev/null and b/decus/vax91a/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax91a/bulletin/bulldir.inc b/decus/vax91a/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..6c532f6f2efe95090dec6b8d157bcc80f20c2e32
Binary files /dev/null and b/decus/vax91a/bulletin/bulldir.inc differ
diff --git a/decus/vax91a/bulletin/bullet1.com b/decus/vax91a/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..16418bb65e71b7aee5db96e2ba51dbb30fb620da
Binary files /dev/null and b/decus/vax91a/bulletin/bullet1.com differ
diff --git a/decus/vax91a/bulletin/bullet2.com b/decus/vax91a/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..3787179d7c0893e1dda042125a3554d6814a22d8
Binary files /dev/null and b/decus/vax91a/bulletin/bullet2.com differ
diff --git a/decus/vax91a/bulletin/bulletin.cld b/decus/vax91a/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..2a0594d9d2b16885f3e2a419dc9c7953950fe062
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin.cld differ
diff --git a/decus/vax91a/bulletin/bulletin.com b/decus/vax91a/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin.com differ
diff --git a/decus/vax91a/bulletin/bulletin.for b/decus/vax91a/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..2f7468b4eb146ac45dddb05d92a2c738461681b5
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin.for differ
diff --git a/decus/vax91a/bulletin/bulletin.hlp b/decus/vax91a/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..56c0f85a1cf1d6d4b08e26107d0d9af3e83be5b9
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin.hlp differ
diff --git a/decus/vax91a/bulletin/bulletin.lnk b/decus/vax91a/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..d763e209be913d73f26fa2fa2fc5553fdf43dbe1
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin.lnk differ
diff --git a/decus/vax91a/bulletin/bulletin0.for b/decus/vax91a/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..f60e532bbfb755b6d4847560ea1f6ff92390e9b3
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin0.for differ
diff --git a/decus/vax91a/bulletin/bulletin1.for b/decus/vax91a/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..1c317dd1cc51d6f37bdf460809af4ed02805087a
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin1.for differ
diff --git a/decus/vax91a/bulletin/bulletin10.for b/decus/vax91a/bulletin/bulletin10.for
new file mode 100755
index 0000000000000000000000000000000000000000..a40661f5ec77d27284d74c9e75d8583cd5dbf060
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin10.for differ
diff --git a/decus/vax91a/bulletin/bulletin2.for b/decus/vax91a/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..a4cde22487c44000b2fded1f4868b9114bdaadc0
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin2.for differ
diff --git a/decus/vax91a/bulletin/bulletin3.for b/decus/vax91a/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..b4da4878e556902cfbd81b1408a23f5ab8ef21d0
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin3.for differ
diff --git a/decus/vax91a/bulletin/bulletin4.for b/decus/vax91a/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..d0e86c79b83bf193c7d4455c62035dcbe6dee31f
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin4.for differ
diff --git a/decus/vax91a/bulletin/bulletin5.for b/decus/vax91a/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..6b60d045f565acc62d2deb42b324abb28cd918dc
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin5.for differ
diff --git a/decus/vax91a/bulletin/bulletin6.for b/decus/vax91a/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..862335febd7633bd1be87681184f81b7091aa009
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin6.for differ
diff --git a/decus/vax91a/bulletin/bulletin7.for b/decus/vax91a/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..692351a44d31ba0110cb579ccdf7fc760d10f05a
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin7.for differ
diff --git a/decus/vax91a/bulletin/bulletin8.for b/decus/vax91a/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..b9c2fa9ef10736aa2d788e3da424e4a14be1cb32
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin8.for differ
diff --git a/decus/vax91a/bulletin/bulletin9.for b/decus/vax91a/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..1b88136e7b91a5068eea9e68fc4418a008e12930
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin9.for differ
diff --git a/decus/vax91a/bulletin/bulletin_ann.txt b/decus/vax91a/bulletin/bulletin_ann.txt
new file mode 100755
index 0000000000000000000000000000000000000000..c0fdcff77bb97b5ee8cb9f439e96ed52cc7cf4d3
Binary files /dev/null and b/decus/vax91a/bulletin/bulletin_ann.txt differ
diff --git a/decus/vax91a/bulletin/bullfiles.inc b/decus/vax91a/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..3ab462bf2e56dd9ec5f3af16dc74400d652c83ce
Binary files /dev/null and b/decus/vax91a/bulletin/bullfiles.inc differ
diff --git a/decus/vax91a/bulletin/bullfolder.inc b/decus/vax91a/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..0321be5419f39b17452ef2b95edcd0d197d5915a
Binary files /dev/null and b/decus/vax91a/bulletin/bullfolder.inc differ
diff --git a/decus/vax91a/bulletin/bullmain.cld b/decus/vax91a/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..59355d8683aa20f3584178f36c83b9d180587909
Binary files /dev/null and b/decus/vax91a/bulletin/bullmain.cld differ
diff --git a/decus/vax91a/bulletin/bullnews.inc b/decus/vax91a/bulletin/bullnews.inc
new file mode 100755
index 0000000000000000000000000000000000000000..884cd4b4e7370581d32198aeb26e7992b7542553
Binary files /dev/null and b/decus/vax91a/bulletin/bullnews.inc differ
diff --git a/decus/vax91a/bulletin/bullstart.com b/decus/vax91a/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/vax91a/bulletin/bullstart.com differ
diff --git a/decus/vax91a/bulletin/bulluser.inc b/decus/vax91a/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..bef93ee1a1d125b3855d6997267b9fcad7383fb4
Binary files /dev/null and b/decus/vax91a/bulletin/bulluser.inc differ
diff --git a/decus/vax91a/bulletin/create.com b/decus/vax91a/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..408796d624cd5606b0ac4d05df064edd9a12a13e
Binary files /dev/null and b/decus/vax91a/bulletin/create.com differ
diff --git a/decus/vax91a/bulletin/dclremote.com b/decus/vax91a/bulletin/dclremote.com
new file mode 100755
index 0000000000000000000000000000000000000000..2c8b5ba8e1f1d24135d8f62e8977667d0ab5ff68
Binary files /dev/null and b/decus/vax91a/bulletin/dclremote.com differ
diff --git a/decus/vax91a/bulletin/handout.txt b/decus/vax91a/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..964ed0ec921e06f3340e9593fd7552168a1067da
Binary files /dev/null and b/decus/vax91a/bulletin/handout.txt differ
diff --git a/decus/vax91a/bulletin/install.com b/decus/vax91a/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..35680c5685788ecb15f70c7af8a641704cc8cefc
Binary files /dev/null and b/decus/vax91a/bulletin/install.com differ
diff --git a/decus/vax91a/bulletin/install_remote.com b/decus/vax91a/bulletin/install_remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..93ae3b1bb784e75b1617e2af2b092bfa1cae07ef
Binary files /dev/null and b/decus/vax91a/bulletin/install_remote.com differ
diff --git a/decus/vax91a/bulletin/instruct.com b/decus/vax91a/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/vax91a/bulletin/instruct.com differ
diff --git a/decus/vax91a/bulletin/instruct.txt b/decus/vax91a/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vax91a/bulletin/instruct.txt differ
diff --git a/decus/vax91a/bulletin/login.com b/decus/vax91a/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..db86b1d3c4c892235d5c896df3d265f7887f214a
Binary files /dev/null and b/decus/vax91a/bulletin/login.com differ
diff --git a/decus/vax91a/bulletin/makefile b/decus/vax91a/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..9b4039d8687714252d6b175c44a57a778ad04766
Binary files /dev/null and b/decus/vax91a/bulletin/makefile differ
diff --git a/decus/vax91a/bulletin/mx.com b/decus/vax91a/bulletin/mx.com
new file mode 100755
index 0000000000000000000000000000000000000000..9db57dca0444cbc54f1eeb278cbbb446b259207e
Binary files /dev/null and b/decus/vax91a/bulletin/mx.com differ
diff --git a/decus/vax91a/bulletin/news.txt b/decus/vax91a/bulletin/news.txt
new file mode 100755
index 0000000000000000000000000000000000000000..57a583455431e33b603fef92fc1919d8a4737b00
Binary files /dev/null and b/decus/vax91a/bulletin/news.txt differ
diff --git a/decus/vax91a/bulletin/nonsystem.txt b/decus/vax91a/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..fc9e1d24b75d04e28a4f8565da0964bef20fc6fc
Binary files /dev/null and b/decus/vax91a/bulletin/nonsystem.txt differ
diff --git a/decus/vax91a/bulletin/optimize_rms.com b/decus/vax91a/bulletin/optimize_rms.com
new file mode 100755
index 0000000000000000000000000000000000000000..5ce90fba3fb2ed5fa0f73013fe87ce852488baa8
Binary files /dev/null and b/decus/vax91a/bulletin/optimize_rms.com differ
diff --git a/decus/vax91a/bulletin/pmdf.com b/decus/vax91a/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..ff10fbfb4a6fe414c6308d33ab2e2b00fbf76008
Binary files /dev/null and b/decus/vax91a/bulletin/pmdf.com differ
diff --git a/decus/vax91a/bulletin/remote.com b/decus/vax91a/bulletin/remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..5cc6fbf88780364f4639e3581d10bf442e7dc58e
Binary files /dev/null and b/decus/vax91a/bulletin/remote.com differ
diff --git a/decus/vax91a/bulletin/setuser.mar b/decus/vax91a/bulletin/setuser.mar
new file mode 100755
index 0000000000000000000000000000000000000000..8471b79ad169dd6c4fc51efe6cb9400e1b088d54
Binary files /dev/null and b/decus/vax91a/bulletin/setuser.mar differ
diff --git a/decus/vax91a/bulletin/writemsg.txt b/decus/vax91a/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6cc45158f156ce88563201952e36bd4698c9fe28
Binary files /dev/null and b/decus/vax91a/bulletin/writemsg.txt differ
diff --git a/decus/vax91b/gce91b/bulletin/allmacs.mar b/decus/vax91b/gce91b/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..6808d90a40d423e474aa42ed607eedd229fab2b4
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/allmacs.mar differ
diff --git a/decus/vax91b/gce91b/bulletin/bullcoms1.hlp b/decus/vax91b/gce91b/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..9359abf2fe7302a3f50a9bdab701959d8cce78ca
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax91b/gce91b/bulletin/bullcoms2.hlp b/decus/vax91b/gce91b/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..3ef351c9201bd2b9dc8fd126264794dfcfb25eee
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax91b/gce91b/bulletin/bullet1.com b/decus/vax91b/gce91b/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..ad844ce61ab5be62e0c86962e721fe97742b5512
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bullet1.com differ
diff --git a/decus/vax91b/gce91b/bulletin/bullet2.com b/decus/vax91b/gce91b/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..e2157fc960b8e238da6543fe733f406fa5fa9d8a
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bullet2.com differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin.ann b/decus/vax91b/gce91b/bulletin/bulletin.ann
new file mode 100755
index 0000000000000000000000000000000000000000..477f3e830de8b7636ee69035088587422b546e22
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin.ann differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin.for b/decus/vax91b/gce91b/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..aa57d4b05042b91466cc1c77f749655b90156148
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin0.for b/decus/vax91b/gce91b/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..6aa7a20cdfa87af632076b2c27762fb361109a3e
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin0.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin1.for b/decus/vax91b/gce91b/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..5d05efd6f57c6d6eba61fda03e522a81d49c2ef6
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin1.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin10.for b/decus/vax91b/gce91b/bulletin/bulletin10.for
new file mode 100755
index 0000000000000000000000000000000000000000..f387770dd5cd0dc6abf3cc2ab804f9a9611141f1
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin10.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin11.for b/decus/vax91b/gce91b/bulletin/bulletin11.for
new file mode 100755
index 0000000000000000000000000000000000000000..58041cfe6e1f511c24f578520cbbdaa6594aaebe
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin11.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin2.for b/decus/vax91b/gce91b/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..f77566e68e52844fd638230c807d792f721ceeba
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin2.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin3.for b/decus/vax91b/gce91b/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..bff60417a509308464ec7cdbe2745658ff30b7ab
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin3.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin4.for b/decus/vax91b/gce91b/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..1fc11af5d4ecce9a8d635c5806531f7b9a337665
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin4.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin5.for b/decus/vax91b/gce91b/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..891d1a683616fce58cebf85d1cf54346805d8372
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin5.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin6.for b/decus/vax91b/gce91b/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..0dd9c15fc400e24b46062de5903b9fa3757e0f33
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin6.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin7.for b/decus/vax91b/gce91b/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..a9cacf13ad2db195597c9a94fbd8841481b7d063
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin7.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin8.for b/decus/vax91b/gce91b/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..382d553f7847bf01b7e6b003042a8e58081a9662
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin8.for differ
diff --git a/decus/vax91b/gce91b/bulletin/bulletin9.for b/decus/vax91b/gce91b/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..b55b6a8253335a4b0570737e5baf0fbd84af3a6a
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/bulletin9.for differ
diff --git a/decus/vax91b/gce91b/bulletin/mx.com b/decus/vax91b/gce91b/bulletin/mx.com
new file mode 100755
index 0000000000000000000000000000000000000000..3b57fc82631a1eab8c14e175823f8a7d7e111297
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/mx.com differ
diff --git a/decus/vax91b/gce91b/bulletin/news.com b/decus/vax91b/gce91b/bulletin/news.com
new file mode 100755
index 0000000000000000000000000000000000000000..c50c044b5d6d5090f8a0104d6de2cbf482576a41
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/news.com differ
diff --git a/decus/vax91b/gce91b/bulletin/pmdf.com b/decus/vax91b/gce91b/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..a05d6220d08c8e0606a4d0442658c5dd5cf92440
Binary files /dev/null and b/decus/vax91b/gce91b/bulletin/pmdf.com differ
diff --git a/decus/vax92a/bulletin/aaareadme.txt b/decus/vax92a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..fbabe5d2a97f192448a5ceab9e622be0840224c8
Binary files /dev/null and b/decus/vax92a/bulletin/aaareadme.txt differ
diff --git a/decus/vax92a/bulletin/board_digest.com b/decus/vax92a/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..c8e9b275dc287da0079a32cccfd5091e8ef9d15a
Binary files /dev/null and b/decus/vax92a/bulletin/board_digest.com differ
diff --git a/decus/vax92a/bulletin/board_special.com b/decus/vax92a/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6ff014483565e3b6f13a05e42ba24b8178f9da3
Binary files /dev/null and b/decus/vax92a/bulletin/board_special.com differ
diff --git a/decus/vax92a/bulletin/bullcoms1.hlp b/decus/vax92a/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..68814d3a5ffda7c34783aca537d04530d240ebd9
Binary files /dev/null and b/decus/vax92a/bulletin/bullcoms1.hlp differ
diff --git a/decus/vax92a/bulletin/bullcoms2.hlp b/decus/vax92a/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..82c20f82cc9089468654c1d7a62cf496f9e55e3a
Binary files /dev/null and b/decus/vax92a/bulletin/bullcoms2.hlp differ
diff --git a/decus/vax92a/bulletin/bulletin.ann b/decus/vax92a/bulletin/bulletin.ann
new file mode 100755
index 0000000000000000000000000000000000000000..c7c256cc32599959576bdfe3bb7336ab961caa12
Binary files /dev/null and b/decus/vax92a/bulletin/bulletin.ann differ
diff --git a/decus/vax92a/bulletin/bulletin.cld b/decus/vax92a/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..d19aa2d72df3013ca204bc8507344e25181b292f
Binary files /dev/null and b/decus/vax92a/bulletin/bulletin.cld differ
diff --git a/decus/vax92a/bulletin/bulletin.com b/decus/vax92a/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vax92a/bulletin/bulletin.com differ
diff --git a/decus/vax92a/bulletin/bulletin.hlp b/decus/vax92a/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..f8f3a479b2f424f3c77c552a1a83579b33d2c70c
Binary files /dev/null and b/decus/vax92a/bulletin/bulletin.hlp differ
diff --git a/decus/vax92a/bulletin/bulletin.lnk b/decus/vax92a/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..4d81da42ae9fe6090f7e3e3d3a27249fbeaf579d
Binary files /dev/null and b/decus/vax92a/bulletin/bulletin.lnk differ
diff --git a/decus/vax92a/bulletin/bulletin_source.tlb b/decus/vax92a/bulletin/bulletin_source.tlb
new file mode 100755
index 0000000000000000000000000000000000000000..7fa5e25df8de46eeb565a283d8ecdd1dea4706df
Binary files /dev/null and b/decus/vax92a/bulletin/bulletin_source.tlb differ
diff --git a/decus/vax92a/bulletin/bullstart.com b/decus/vax92a/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/vax92a/bulletin/bullstart.com differ
diff --git a/decus/vax92a/bulletin/dclremote.com b/decus/vax92a/bulletin/dclremote.com
new file mode 100755
index 0000000000000000000000000000000000000000..0522f9dfd830aa5553d72307e75640d502cda633
Binary files /dev/null and b/decus/vax92a/bulletin/dclremote.com differ
diff --git a/decus/vax92a/bulletin/extract_tlb.com b/decus/vax92a/bulletin/extract_tlb.com
new file mode 100755
index 0000000000000000000000000000000000000000..97ff60ecabd715be4062c8d70003a42e5d5a3593
Binary files /dev/null and b/decus/vax92a/bulletin/extract_tlb.com differ
diff --git a/decus/vax92a/bulletin/handout.txt b/decus/vax92a/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vax92a/bulletin/handout.txt differ
diff --git a/decus/vax92a/bulletin/install.com b/decus/vax92a/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..35680c5685788ecb15f70c7af8a641704cc8cefc
Binary files /dev/null and b/decus/vax92a/bulletin/install.com differ
diff --git a/decus/vax92a/bulletin/install_remote.com b/decus/vax92a/bulletin/install_remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..93ae3b1bb784e75b1617e2af2b092bfa1cae07ef
Binary files /dev/null and b/decus/vax92a/bulletin/install_remote.com differ
diff --git a/decus/vax92a/bulletin/instruct.com b/decus/vax92a/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..973fbf5f53e86f8a67df1c8c25db73afce6c151e
Binary files /dev/null and b/decus/vax92a/bulletin/instruct.com differ
diff --git a/decus/vax92a/bulletin/instruct.txt b/decus/vax92a/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..fdfb8f295a9c93cb2fc47bfde34ae75c42136a4e
Binary files /dev/null and b/decus/vax92a/bulletin/instruct.txt differ
diff --git a/decus/vax92a/bulletin/login.com b/decus/vax92a/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..1f6f24540ce1c78df34f085b99ac36c181dff7f3
Binary files /dev/null and b/decus/vax92a/bulletin/login.com differ
diff --git a/decus/vax92a/bulletin/news.com b/decus/vax92a/bulletin/news.com
new file mode 100755
index 0000000000000000000000000000000000000000..44923a1128cc98cdae479391095abcde1d333517
Binary files /dev/null and b/decus/vax92a/bulletin/news.com differ
diff --git a/decus/vax92a/bulletin/news.txt b/decus/vax92a/bulletin/news.txt
new file mode 100755
index 0000000000000000000000000000000000000000..77d8a24c4ff4ef5c996306579d6277f060de26f7
Binary files /dev/null and b/decus/vax92a/bulletin/news.txt differ
diff --git a/decus/vax92a/bulletin/nonsystem.txt b/decus/vax92a/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..aaf9117b1b41f89fcca08eec69c84cf6a3cfab17
Binary files /dev/null and b/decus/vax92a/bulletin/nonsystem.txt differ
diff --git a/decus/vax92a/bulletin/optimize_rms.com b/decus/vax92a/bulletin/optimize_rms.com
new file mode 100755
index 0000000000000000000000000000000000000000..5ce90fba3fb2ed5fa0f73013fe87ce852488baa8
Binary files /dev/null and b/decus/vax92a/bulletin/optimize_rms.com differ
diff --git a/decus/vax92a/bulletin/remote.com b/decus/vax92a/bulletin/remote.com
new file mode 100755
index 0000000000000000000000000000000000000000..bc4ec8538124bc9f57825edc284ff0441cbe2334
Binary files /dev/null and b/decus/vax92a/bulletin/remote.com differ
diff --git a/decus/vax92a/bulletin/writemsg.txt b/decus/vax92a/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6ee4ec02e151fc32828c4e890830eee127cf5da3
Binary files /dev/null and b/decus/vax92a/bulletin/writemsg.txt differ
diff --git a/decus/vax92a/gce92a/net92a/bulletin_howtoget.txt b/decus/vax92a/gce92a/net92a/bulletin_howtoget.txt
new file mode 100755
index 0000000000000000000000000000000000000000..92a240fbae5736c2043e6c4b04b31f64ae1260ec
Binary files /dev/null and b/decus/vax92a/gce92a/net92a/bulletin_howtoget.txt differ
diff --git a/decus/vax92b/bulletin/aaareadme.txt b/decus/vax92b/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8816073f80ff19719109c96e86c0e7ddb9b329dc
Binary files /dev/null and b/decus/vax92b/bulletin/aaareadme.txt differ
diff --git a/decus/vax92b/bulletin/bull_news.c b/decus/vax92b/bulletin/bull_news.c
new file mode 100755
index 0000000000000000000000000000000000000000..96b9f9be70e3fdad62f5adabfe154aa105396324
--- /dev/null
+++ b/decus/vax92b/bulletin/bull_news.c
@@ -0,0 +1,414 @@
+#include <descrip.h>
+#include "sys$library:iodef.h"
+
+#if MULTINET
+
+#include "multinet_root:[multinet.include.sys]types.h"
+#include "multinet_root:[multinet.include.sys]socket.h"
+#include "multinet_root:[multinet.include.netinet]in.h"
+#include "multinet_root:[multinet.include]netdb.h"
+#include "multinet_root:[multinet.include]errno.h"
+#include "multinet_root:[multinet.include.vms]inetiodef.h"
+
+static char inet[7] = "INET0:";
+$DESCRIPTOR(inet_d,inet);
+
+#else
+
+#if UCX
+
+#include <ucx$inetdef.h>
+
+struct sockaddr {
+  short inet_family;
+  short inet_port;
+  int inet_adrs;
+  char bklb[8];
+  };
+
+struct itlist { int lgth; struct sockaddr *hst; };
+
+static short sck_parm[2];
+static struct sockaddr local_host, remote_host;
+struct itlist lhst_adrs, rhst_adrs;
+
+static char ucxdev[11] = "UCX$DEVICE";
+$DESCRIPTOR(ucxdev_d,ucxdev);
+
+static int addr_buff;
+
+#define htons(x) ((unsigned short)((x<<8)|(x>>8)))
+
+#else
+
+#if TWG
+
+#include <types.h>
+#include <socket.h>
+#include <netdb.h>
+#include <in.h>
+#include <inetiodef.h>
+
+static char inet[6] = "INET:";
+$DESCRIPTOR(inet_d,inet);
+
+#else
+
+#define CMU 1
+static char ip[4] = "IP:";
+$DESCRIPTOR(ip_d,ip);
+
+#endif
+
+#endif
+
+#endif
+
+static char task[20];
+$DESCRIPTOR(task_d,task);
+
+static int s;
+
+static struct iosb {
+	short status;
+	short size;
+	int info;
+} iosb;
+
+#define TCP 0
+#define DECNET 1
+
+static int mode = TCP;
+
+news_get_chan()
+{return(s);}
+
+news_set_chan(i)
+int *i;
+{s = *i;}
+
+news_disconnect()
+{
+#if UCX
+	sys$cancel(s);
+	sys$qiow(0,s,IO$_DEACCESS,0,0,0,0,0,0,0,0,0);
+#endif
+	sys$dassgn(s);
+}
+
+#if MULTINET || TWG
+
+static struct hostent *hp;
+static struct sockaddr_in sin;
+
+#endif
+
+int *node;
+
+news_gethost()
+{
+	/*
+	 *  Get the IP address of the NEWS host.
+	 *  As of MULTINET 3.0, cannot be done at AST level
+	 *  so can't do in NEWS_ASSIGN(), as BULLCP calls it at
+	 *  AST level if the decnet gateway feature is used.
+	 */
+#if TWG || (MULTINET && defined(__GNUC__))
+	struct hostent *gethostbyname();
+#else
+#if MULTINET
+	struct hostent *GETHOSTBYNAME1();
+#endif
+#endif
+
+	node = getenv("BULL_NEWS_SERVER");
+	if (!node) return(0);
+	if (!strchr(node,'.')) return(1);
+
+#if TWG || (MULTINET && defined(__GNUC__))
+	hp = gethostbyname(node);
+#else
+#if MULTINET
+	hp = GETHOSTBYNAME1(node);
+#endif
+#endif
+	return(1);
+}
+
+news_assign()
+{
+	int n;
+
+	if (!strchr(node,'.')) {
+	   strcpy(&task[0],node);
+	   n = strlen(node);
+	   strcpy(&task[n],"::\"TASK=NNTP\"");
+	   task_d.dsc$w_length = 13 + n;
+	   if (!(sys$assign(&task_d,&s,0,0) & 1)) return(0);
+	   mode = DECNET;
+	   return(1);
+	}
+#if MULTINET || TWG
+	/*
+	 *  Create a "sockaddr_in" structure which describes the remote
+	 *  IP address we want to send to (from gethostbyname()).
+	 */
+
+        if (!hp) {
+          int h[4],i;
+          if (sscanf(node,"%d.%d.%d.%d",&h[0],&h[1],&h[2],&h[3]) == 4) {
+            for (i=0;i<4;i++) if (h[i] < 0 || h[i] > 255) return(0);
+	    sin.sin_addr.s_addr = (h[3]<<24)+(h[2]<<16)+(h[1]<<8)+(h[0]);
+	  } else
+	    return(0);
+	  sin.sin_family = AF_INET;
+	}
+        else {
+ 	  sin.sin_family = hp->h_addrtype;
+	  memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
+        }
+#if TWG || (MULTINET && defined(__GNUC__))
+	sin.sin_port = htons(119);
+#else
+	sin.sin_port = HTONS1(119);
+#endif
+
+	/*
+	 *  Create an IP-family socket on which to make the connection
+	 */
+
+	if (!(sys$assign(&inet_d,&s,0,0) & 1)) return(0);
+#else
+#if UCX
+        if (!(sys$assign(&ucxdev_d,&s,0,0) & 1)) return(0);
+	{
+           short retlen;
+	   struct dsc$descriptor host_name
+		= {strlen(node),DSC$K_CLASS_S,DSC$K_DTYPE_T,node};
+	   int comm = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYNAME;
+	   struct dsc$descriptor command
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&comm};
+	   struct dsc$descriptor host_ad
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&addr_buff};
+	   struct iosb nam_iosb;
+
+           if (!(sys$qiow(0,s,IO$_ACPCONTROL,&nam_iosb,0,0,
+                       &command,&host_name,&retlen,&host_ad,0,0) & 1)
+               || !(nam_iosb.status & 1)) {
+              sys$dassgn(s);
+	      return(0);
+	   }
+	}
+#else
+	if (!(sys$assign(&ip_d,&s,0,0) & 1)) return(0);
+#endif
+#endif
+	return(1);
+}
+
+news_socket()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qiow(0,s,IO$_SOCKET,&iosb,0,0,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qiow(0,s,IO$_SETMODE,&iosb,0,0,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+
+	return(1);
+}
+
+news_socket_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qio(*efn,s,IO$_SOCKET,biosb,astadr,*astprm,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) ) return(0);
+#else
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qio(0,s,IO$_SETMODE,biosb,astadr,*astprm,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) ) return(0);
+#else
+	return(-1);
+#endif
+#endif
+
+	return(1);
+}
+
+news_create()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qiow(0,s,IO$_CONNECT,&iosb,0,0,&sin,sizeof(sin),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+#if UCX
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qiow(0,s,IO$_ACCESS,&iosb,0,0,0,0,&rhst_adrs,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+	if (!(sys$qiow(0,s,IO$_CREATE,&iosb,0,0,node,119,0,1,0,300) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#endif
+
+	return(1);
+}
+
+news_create_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qio(*efn,s,IO$_CONNECT,biosb,astadr
+		,*astprm,&sin,sizeof(sin),0,0,0,0) & 1)) return(0);
+#else
+#if UCX
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qio(*efn,s,IO$_ACCESS,biosb,astadr,*astprm,0,
+		0,&rhst_adrs,0,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_CREATE,biosb,astadr,*astprm,node,
+		119,0,1,0,300) & 1))
+	   return(0);
+#endif
+#endif
+
+	return(1);
+}
+
+news_connect()
+{
+	if (!news_gethost()) return(0);
+	if (!news_assign()) return(0);
+	if (!news_socket()) return(0);
+	return(news_create());
+}
+
+news_write_packet(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+#if CMU
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,!mode,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#else
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_write_packet_bullcp(efn,biosb,astadr,astprm,buf,len)
+int *biosb,*astadr,*astprm,*efn,*buf,*len;
+{
+#if CMU
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,!mode,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,0,0,0) & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_read_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+	if (!(sys$qiow(0,s,IO$_READVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+	n = iosb.size;
+
+	return(n);
+}
+
+news_gethostname(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	if (mode == DECNET) return (-1);
+#if TWG || (MULTINET && defined(__GNUC__))
+	return(gethostname(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+#if MULTINET
+	return(GETHOSTNAME1(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+	return(-1);
+#endif
+#endif
+}
diff --git a/decus/vax92b/bulletin/bulletin.announce b/decus/vax92b/bulletin/bulletin.announce
new file mode 100755
index 0000000000000000000000000000000000000000..4ad41e994835d8f26fe72ba1fd2e8a8a43b1a65e
Binary files /dev/null and b/decus/vax92b/bulletin/bulletin.announce differ
diff --git a/decus/vax92b/bulletin/bulletin_announce.txt b/decus/vax92b/bulletin/bulletin_announce.txt
new file mode 100755
index 0000000000000000000000000000000000000000..449f1073641ff67104c663f8473f5354d77af43b
Binary files /dev/null and b/decus/vax92b/bulletin/bulletin_announce.txt differ
diff --git a/decus/vlt95b/bulletin/aaareadme.txt b/decus/vlt95b/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..e3d297e202bd916e66b2326de901482ce4fb8859
Binary files /dev/null and b/decus/vlt95b/bulletin/aaareadme.txt differ
diff --git a/decus/vlt95b/bulletin/allmacs.mar b/decus/vlt95b/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..4a6072cffdf2449766b6f0edc21b8eee640b7308
Binary files /dev/null and b/decus/vlt95b/bulletin/allmacs.mar differ
diff --git a/decus/vlt95b/bulletin/allmacs_axp.mar b/decus/vlt95b/bulletin/allmacs_axp.mar
new file mode 100755
index 0000000000000000000000000000000000000000..4405fa1809177e174b0a7796bc3b4581ed1ee772
Binary files /dev/null and b/decus/vlt95b/bulletin/allmacs_axp.mar differ
diff --git a/decus/vlt95b/bulletin/board_digest.com b/decus/vlt95b/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/vlt95b/bulletin/board_digest.com differ
diff --git a/decus/vlt95b/bulletin/board_special.com b/decus/vlt95b/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6ff014483565e3b6f13a05e42ba24b8178f9da3
Binary files /dev/null and b/decus/vlt95b/bulletin/board_special.com differ
diff --git a/decus/vlt95b/bulletin/bull_news.c b/decus/vlt95b/bulletin/bull_news.c
new file mode 100755
index 0000000000000000000000000000000000000000..afd6a68e6ea7845a8862a2e807a5e3da3409a4e3
Binary files /dev/null and b/decus/vlt95b/bulletin/bull_news.c differ
diff --git a/decus/vlt95b/bulletin/bull_newsdummy.for b/decus/vlt95b/bulletin/bull_newsdummy.for
new file mode 100755
index 0000000000000000000000000000000000000000..9bc04a28d243c2270dabf0b669b7efdceaf4079c
Binary files /dev/null and b/decus/vlt95b/bulletin/bull_newsdummy.for differ
diff --git a/decus/vlt95b/bulletin/bullcom.cld b/decus/vlt95b/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..ea2b6c3d16090670f5c22c36db3ba5295d1f5c22
Binary files /dev/null and b/decus/vlt95b/bulletin/bullcom.cld differ
diff --git a/decus/vlt95b/bulletin/bullcoms1.hlp b/decus/vlt95b/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..e7cb71f256ed111bdbbb8e8b590b7f01f03be23e
Binary files /dev/null and b/decus/vlt95b/bulletin/bullcoms1.hlp differ
diff --git a/decus/vlt95b/bulletin/bullcoms2.hlp b/decus/vlt95b/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..02250c4ecf28e01f779de7532967ac8a2300535f
Binary files /dev/null and b/decus/vlt95b/bulletin/bullcoms2.hlp differ
diff --git a/decus/vlt95b/bulletin/bulldir.inc b/decus/vlt95b/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..9f9d356f1ebfa80c3895d9343dbd9e4b0af165f1
Binary files /dev/null and b/decus/vlt95b/bulletin/bulldir.inc differ
diff --git a/decus/vlt95b/bulletin/bullet1.com b/decus/vlt95b/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..7c8b72f6a76d810110fe15b6ad4e91bd52016e25
Binary files /dev/null and b/decus/vlt95b/bulletin/bullet1.com differ
diff --git a/decus/vlt95b/bulletin/bullet2.com b/decus/vlt95b/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..8a5830a66b70652b3a5fa2edc98da2d99fb19e0b
Binary files /dev/null and b/decus/vlt95b/bulletin/bullet2.com differ
diff --git a/decus/vlt95b/bulletin/bulletin.cld b/decus/vlt95b/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..7faee4731dc00791d45b3f85429bef300f31f5ff
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin.cld differ
diff --git a/decus/vlt95b/bulletin/bulletin.com b/decus/vlt95b/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin.com differ
diff --git a/decus/vlt95b/bulletin/bulletin.for b/decus/vlt95b/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..f60ce6942820efa4d25de246cc1675cf01fcdb6b
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin.for differ
diff --git a/decus/vlt95b/bulletin/bulletin.hlp b/decus/vlt95b/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..696f7a6fcfc46f611af407a2b8b74bc205861d57
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin.hlp differ
diff --git a/decus/vlt95b/bulletin/bulletin.lnk b/decus/vlt95b/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..48f2676823a3f51eadbde88731061b86bf6bbc3a
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin.lnk differ
diff --git a/decus/vlt95b/bulletin/bulletin0.for b/decus/vlt95b/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..650c62a7f682ff43c7d4f44a749fa2ba92fbe3d7
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin0.for differ
diff --git a/decus/vlt95b/bulletin/bulletin1.for b/decus/vlt95b/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..d656a97205c17178fc405b7d36c3accbd44c9b37
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin1.for differ
diff --git a/decus/vlt95b/bulletin/bulletin10.for b/decus/vlt95b/bulletin/bulletin10.for
new file mode 100755
index 0000000000000000000000000000000000000000..3d78a038388e22889e113ea655c5367c491644b4
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin10.for differ
diff --git a/decus/vlt95b/bulletin/bulletin11.for b/decus/vlt95b/bulletin/bulletin11.for
new file mode 100755
index 0000000000000000000000000000000000000000..6f663e1016ff652f7270791aadf6359ec2e25a19
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin11.for differ
diff --git a/decus/vlt95b/bulletin/bulletin2.for b/decus/vlt95b/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..6070e62a631db7fd87cb79399810dc98105dcb7d
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin2.for differ
diff --git a/decus/vlt95b/bulletin/bulletin3.for b/decus/vlt95b/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..e02b2bd4e7de3776cbb8e5f4c3274355ae9779d5
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin3.for differ
diff --git a/decus/vlt95b/bulletin/bulletin4.for b/decus/vlt95b/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..04488e00d399db5b51358d23f3e66ec8ceecda57
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin4.for differ
diff --git a/decus/vlt95b/bulletin/bulletin5.for b/decus/vlt95b/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..5a85fc517aecdc4953c9839e99d01aabc4f2eb2f
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin5.for differ
diff --git a/decus/vlt95b/bulletin/bulletin6.for b/decus/vlt95b/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..ed30cda9c7eaf3b417422c5de571ab8177ff1a1b
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin6.for differ
diff --git a/decus/vlt95b/bulletin/bulletin7.for b/decus/vlt95b/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..3589f42c19d093fd0426f6822f8246135a0b091f
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin7.for differ
diff --git a/decus/vlt95b/bulletin/bulletin8.for b/decus/vlt95b/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..7e1ad4f86486e989618e4b693b461356fb10ae8d
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin8.for differ
diff --git a/decus/vlt95b/bulletin/bulletin9.for b/decus/vlt95b/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..9aec05383d8444096fdec1a5dc282e73d1763b0c
Binary files /dev/null and b/decus/vlt95b/bulletin/bulletin9.for differ
diff --git a/decus/vlt95b/bulletin/bullfiles.inc b/decus/vlt95b/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..37bde435b1808ea284d5217f21fafd815bb1d52c
Binary files /dev/null and b/decus/vlt95b/bulletin/bullfiles.inc differ
diff --git a/decus/vlt95b/bulletin/bullfolder.inc b/decus/vlt95b/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..66c3ebb63d12e56679ad279a549cdb5a8db40fe6
Binary files /dev/null and b/decus/vlt95b/bulletin/bullfolder.inc differ
diff --git a/decus/vlt95b/bulletin/bullmain.cld b/decus/vlt95b/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..1eb4f959603b8042d1546c47518b6477f2dd04e5
Binary files /dev/null and b/decus/vlt95b/bulletin/bullmain.cld differ
diff --git a/decus/vlt95b/bulletin/bullnews.inc b/decus/vlt95b/bulletin/bullnews.inc
new file mode 100755
index 0000000000000000000000000000000000000000..6600ba017c36f39574caf53bdca982f45788bb7a
Binary files /dev/null and b/decus/vlt95b/bulletin/bullnews.inc differ
diff --git a/decus/vlt95b/bulletin/bullstart.com b/decus/vlt95b/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/vlt95b/bulletin/bullstart.com differ
diff --git a/decus/vlt95b/bulletin/bulluser.inc b/decus/vlt95b/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..89df9193041fb6e1dc9835e34380508edf39c911
Binary files /dev/null and b/decus/vlt95b/bulletin/bulluser.inc differ
diff --git a/decus/vlt95b/bulletin/changes.txt b/decus/vlt95b/bulletin/changes.txt
new file mode 100755
index 0000000000000000000000000000000000000000..538b1c9e47f53c7343eadc640fcd0482a2218f52
Binary files /dev/null and b/decus/vlt95b/bulletin/changes.txt differ
diff --git a/decus/vlt95b/bulletin/cmds.mai b/decus/vlt95b/bulletin/cmds.mai
new file mode 100755
index 0000000000000000000000000000000000000000..b747457a0e66370e0900b57943b54f7f6c1231cc
Binary files /dev/null and b/decus/vlt95b/bulletin/cmds.mai differ
diff --git a/decus/vlt95b/bulletin/copyright.txt b/decus/vlt95b/bulletin/copyright.txt
new file mode 100755
index 0000000000000000000000000000000000000000..9109280949b210763ea1e18b0fe8b77cc9dea657
Binary files /dev/null and b/decus/vlt95b/bulletin/copyright.txt differ
diff --git a/decus/vlt95b/bulletin/create.com b/decus/vlt95b/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..fd4baaa7c4cadad96c5a9c08dd209e761f566515
Binary files /dev/null and b/decus/vlt95b/bulletin/create.com differ
diff --git a/decus/vlt95b/bulletin/handout.txt b/decus/vlt95b/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vlt95b/bulletin/handout.txt differ
diff --git a/decus/vlt95b/bulletin/install.com b/decus/vlt95b/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..530e4a827a5ce3865875fa3ed27d4b02652102a9
Binary files /dev/null and b/decus/vlt95b/bulletin/install.com differ
diff --git a/decus/vlt95b/bulletin/instruct.com b/decus/vlt95b/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..4487801de36fb7dcdcb08028e7f7338cf88a23d8
Binary files /dev/null and b/decus/vlt95b/bulletin/instruct.com differ
diff --git a/decus/vlt95b/bulletin/instruct.txt b/decus/vlt95b/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vlt95b/bulletin/instruct.txt differ
diff --git a/decus/vlt95b/bulletin/login.com b/decus/vlt95b/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..fa69c5013bb2f7098b438f3bf46245ab6ad14508
Binary files /dev/null and b/decus/vlt95b/bulletin/login.com differ
diff --git a/decus/vlt95b/bulletin/makefile b/decus/vlt95b/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..acbf523bb8b33cf8ed938a3498ad8d8954228e5f
Binary files /dev/null and b/decus/vlt95b/bulletin/makefile differ
diff --git a/decus/vlt95b/bulletin/master.com b/decus/vlt95b/bulletin/master.com
new file mode 100755
index 0000000000000000000000000000000000000000..bf37b9cca94e6da50930cbbc79cf54ba00147636
Binary files /dev/null and b/decus/vlt95b/bulletin/master.com differ
diff --git a/decus/vlt95b/bulletin/mx.com b/decus/vlt95b/bulletin/mx.com
new file mode 100755
index 0000000000000000000000000000000000000000..d74d9e5b004afd180933991a979e9dd8129f9a84
Binary files /dev/null and b/decus/vlt95b/bulletin/mx.com differ
diff --git a/decus/vlt95b/bulletin/mx.mai b/decus/vlt95b/bulletin/mx.mai
new file mode 100755
index 0000000000000000000000000000000000000000..3eda561c65e4f42db3cdb6f8d79594eaaca2fefd
Binary files /dev/null and b/decus/vlt95b/bulletin/mx.mai differ
diff --git a/decus/vlt95b/bulletin/news.alt b/decus/vlt95b/bulletin/news.alt
new file mode 100755
index 0000000000000000000000000000000000000000..ef71a6408372d85a7ccfcfb2251d50f75bde1ebe
Binary files /dev/null and b/decus/vlt95b/bulletin/news.alt differ
diff --git a/decus/vlt95b/bulletin/news.com b/decus/vlt95b/bulletin/news.com
new file mode 100755
index 0000000000000000000000000000000000000000..1582a146c764cb5e2c2b163a5fa0940a0fb7c354
Binary files /dev/null and b/decus/vlt95b/bulletin/news.com differ
diff --git a/decus/vlt95b/bulletin/news.create b/decus/vlt95b/bulletin/news.create
new file mode 100755
index 0000000000000000000000000000000000000000..b90a3d3650faea8ba7b4715a854f8085d12624c6
Binary files /dev/null and b/decus/vlt95b/bulletin/news.create differ
diff --git a/decus/vlt95b/bulletin/news.moderators b/decus/vlt95b/bulletin/news.moderators
new file mode 100755
index 0000000000000000000000000000000000000000..b0f3d836093ce5085f63b6519aeaadc17f1626a8
Binary files /dev/null and b/decus/vlt95b/bulletin/news.moderators differ
diff --git a/decus/vlt95b/bulletin/news.txt b/decus/vlt95b/bulletin/news.txt
new file mode 100755
index 0000000000000000000000000000000000000000..eb4969e8a639dfb85ec544d9df9416011198c13b
Binary files /dev/null and b/decus/vlt95b/bulletin/news.txt differ
diff --git a/decus/vlt95b/bulletin/nonsystem.txt b/decus/vlt95b/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/vlt95b/bulletin/nonsystem.txt differ
diff --git a/decus/vlt95b/bulletin/optimize_rms.com b/decus/vlt95b/bulletin/optimize_rms.com
new file mode 100755
index 0000000000000000000000000000000000000000..1d3f04dbac9868f4468b3999e5e80a8b0d91a59c
Binary files /dev/null and b/decus/vlt95b/bulletin/optimize_rms.com differ
diff --git a/decus/vlt95b/bulletin/pmdf.com b/decus/vlt95b/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..de38f11ef0d66ba98dd9dd4c366e070430066eb2
Binary files /dev/null and b/decus/vlt95b/bulletin/pmdf.com differ
diff --git a/decus/vlt95b/bulletin/restart.com b/decus/vlt95b/bulletin/restart.com
new file mode 100755
index 0000000000000000000000000000000000000000..499764c5f0dc3b747c310de50039fa1b03071f17
Binary files /dev/null and b/decus/vlt95b/bulletin/restart.com differ
diff --git a/decus/vlt95b/bulletin/setuser.mar b/decus/vlt95b/bulletin/setuser.mar
new file mode 100755
index 0000000000000000000000000000000000000000..bd3066dbdb50697071e10baed296cbdba9298f78
Binary files /dev/null and b/decus/vlt95b/bulletin/setuser.mar differ
diff --git a/decus/vlt95b/bulletin/update.fil b/decus/vlt95b/bulletin/update.fil
new file mode 100755
index 0000000000000000000000000000000000000000..9544d0824f81a7bbf669668476dbac91d6b0dfdb
Binary files /dev/null and b/decus/vlt95b/bulletin/update.fil differ
diff --git a/decus/vlt95b/bulletin/upgrade.com b/decus/vlt95b/bulletin/upgrade.com
new file mode 100755
index 0000000000000000000000000000000000000000..d1f92d336b99b3517112d7177ced4d6f2d20ab12
Binary files /dev/null and b/decus/vlt95b/bulletin/upgrade.com differ
diff --git a/decus/vlt95b/bulletin/writemsg.txt b/decus/vlt95b/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6ee4ec02e151fc32828c4e890830eee127cf5da3
Binary files /dev/null and b/decus/vlt95b/bulletin/writemsg.txt differ
diff --git a/decus/vlt97a/vmslt97a/bulletin/aaareadme.1st b/decus/vlt97a/vmslt97a/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..2c77e2ab8522245c8062ba0a2c5a4efb561bcf0b
Binary files /dev/null and b/decus/vlt97a/vmslt97a/bulletin/aaareadme.1st differ
diff --git a/decus/vlt97a/vmslt97a/bulletin/aaareadme.txt b/decus/vlt97a/vmslt97a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..88a11b777f3e573ae54d7f30ddbc68d5aebc0d1c
Binary files /dev/null and b/decus/vlt97a/vmslt97a/bulletin/aaareadme.txt differ
diff --git a/decus/vlt97a/vmslt97a/bulletin/bulletin.ann b/decus/vlt97a/vmslt97a/bulletin/bulletin.ann
new file mode 100755
index 0000000000000000000000000000000000000000..26ba811298879af73af01c7fbbf0c89d63f44383
Binary files /dev/null and b/decus/vlt97a/vmslt97a/bulletin/bulletin.ann differ
diff --git a/decus/vlt97a/vmslt97a/bulletin/handout.txt b/decus/vlt97a/vmslt97a/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..57e2514adf8289b85a85fdb96747932a04245d67
Binary files /dev/null and b/decus/vlt97a/vmslt97a/bulletin/handout.txt differ
diff --git a/decus/vlt97a/vmslt97a/bulletin/instruct.txt b/decus/vlt97a/vmslt97a/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..38b07703e02e538447fa2e761e0b4d74141ae6c1
Binary files /dev/null and b/decus/vlt97a/vmslt97a/bulletin/instruct.txt differ
diff --git a/decus/vms95a/gce95a/bulletin/aaareadme b/decus/vms95a/gce95a/bulletin/aaareadme
new file mode 100755
index 0000000000000000000000000000000000000000..617ecd7be08f4e8b9c68ee6cb405f53756f6544b
Binary files /dev/null and b/decus/vms95a/gce95a/bulletin/aaareadme differ
diff --git a/decus/vms95a/gce95a/bulletin/aaareadme.first b/decus/vms95a/gce95a/bulletin/aaareadme.first
new file mode 100755
index 0000000000000000000000000000000000000000..e3d297e202bd916e66b2326de901482ce4fb8859
Binary files /dev/null and b/decus/vms95a/gce95a/bulletin/aaareadme.first differ
diff --git a/decus/vms95b/bulletin/aaareadme.txt b/decus/vms95b/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..4122ae0412d362e4fbec6e5b2413cf9f4001ad59
Binary files /dev/null and b/decus/vms95b/bulletin/aaareadme.txt differ
diff --git a/decus/vmslt00a/bulletin/aaareadme b/decus/vmslt00a/bulletin/aaareadme
new file mode 100755
index 0000000000000000000000000000000000000000..f4cc15c6886875afd04cfd176a813df025fc7375
--- /dev/null
+++ b/decus/vmslt00a/bulletin/aaareadme
@@ -0,0 +1,68 @@
+BULLETIN   is   public   domain   software.    (I   will  gladly  accept
+recommendations for new features,  not  for  changes  that  are  due  to
+"personal" preference.)
+
+If you are running a version of BULLETIN older than 2.11,  this  version
+will  modify  the  format of some of the data files.  (This will be done
+automatically  when  the  new  version  is   run).    After   successful
+installation,  the  older  versions of these files can be removed. NOTE:
+Problems  can  occur if  the  old  version  of BULLETIN is run after the
+data files have been modified.  Such a situation is possible on a
+cluster where each node has installed  the  executable  separately.   To 
+help  installation,  a new command procedure UPGRADE.COM has been 
+included.  Read the comments in the file for information on how to use
+it. 
+ 
+NOTE: The following commands can be sent to BULLETIN@PSFC.MIT.EDU:
+	SEND ALL [SINCE time]	Sends all bulletin files.
+				If SINCE time specified, only files created
+				since that time will be sent.
+	SEND filename		Sends the specified file.	
+	BUGS			Sends a list of the latest bug fixes.
+	HELP or INFO		Sends a brief description of BULLETIN.
+	SUBSCRIBE               Subscribes to mailing list for upgrade
+                                notifications.
+        UNSUBSCRIBE             Unsubscribes from mailing list.
+
+NOTE:  An old bug might have changed the protection on the BULLETIN data
+files.  The protection on all data files (i.e.  B*.DAT,  *.BULLFIL,  and
+*.BULLDIR) should be (RWED,RWED,,).
+
+You will be receiving 22 files (NOT NECESSARILY IN THIS ORDER!):
+	1) BULLETIN.FOR
+	2) BULLETIN0.FOR
+	3) BULLETIN1.FOR
+	4) BULLETIN2.FOR
+	5) BULLETIN3.FOR
+	6) BULLETIN4.FOR
+	7) BULLETIN5.FOR
+	8) BULLETIN6.FOR
+	9) BULLETIN7.FOR
+	10) BULLETIN8.FOR
+	11) BULLETIN9.FOR
+	12) BULLETIN10.FOR
+	13) BULLETIN11.FOR
+	14) ALLMACS.MAR
+	15) BULLCOMS1.HLP
+	16) BULLCOMS2.HLP
+	17) BULLET1.COM
+	18) BULLET2.COM
+	19) PMDF.COM
+	20) MX.COM
+        21) NEWS.COM
+	22) ALLMACS_AXP.MAR
+
+(They  will  be  identified  in  the  SUBJECT  header.)  BULLET1.COM and
+BULLET2.COM are command procedures which when run, will  create  several
+small files.  After you run them, you can delete them.  If you have PMDF
+at your site, you should also run PMDF.COM.  However, this only  applies
+to  PMDF  V3.2  or earlier, as later versions of PMDF have the necessary
+interface code for BULLETIN included in it.  In that case,  or  in  case
+you  don't have PMDF, you can delete it.  The same applies to MX.  Then,
+read AAAREADME.TXT for BULLETN installation instructions.   If  you  are
+using the news feature, NEWS.COM contains files which pertain to news.
+
+NOTE: When creating these files (using the EXTRACT command) from the VMS
+MAIL utility, you will have to strip  off  any  mail  headers  that  are
+present,  including blank lines.
+                                              MRL@PSFC.MIT.EDU
diff --git a/decus/vmslt00a/bulletin/aaareadme.install b/decus/vmslt00a/bulletin/aaareadme.install
new file mode 100755
index 0000000000000000000000000000000000000000..e6704090acb6e1129a06cae4c7922bf902c83c09
--- /dev/null
+++ b/decus/vmslt00a/bulletin/aaareadme.install
@@ -0,0 +1,202 @@
+The following are instructions for creating and installing the BULLETIN
+utility. None of the command procedures included here are sophisticated, so it
+is likely that several modifications will have to be made by the installer.
+The installer should enable all privileges before installation.
+
+Once installation is complete, it is suggested that the installer enter
+BULLETIN and read HELP FOLDERS to see the options available when creating
+or modifying folders.  BULLETIN creates a default folder called GENERAL
+which is a SYSTEM folder (allows messages to be posted which are displayed
+in full when people login.)  This folder can be modified (name changed,
+SYSTEM setting removed, etc.), but it will remain the default folder
+which is selected when BULLETIN is entered, and it cannot be deleted.
+
+One of the main uses of BULLETIN, besides storage of messages that are manually
+entered by users, is storage of messages from network mailing lists.  This is
+done by using the BBOARD feature, which is enabled using the SET BBOARD command
+inside BULLETIN.  The alternative method is for mail messages to be written
+directly by a mailing program by calling internal BULLETIN routines.  Such a
+a program has been written for the popular mail utilities PMDF and MX.  If you
+wish to do so for another utility, read the text file WRITEMSG.TXT.  I would be
+glad to include any such programs with my distribution if you think such a
+program would be of use to other users.
+
+By default, BULLETIN uses the format IN%"email-address" when sending mail via
+VMS MAIL.  The IN% is hardcoded in BULLNEWS.INC.  If you use a different
+protocol, you should either change the reference in that file, or you can
+define logical name BULL_NEWS_MAILER to point to the new protocol, i.e.
+DEFINE/SYSTEM BULL_NEWS_MAILER "MX%". 
+                   
+If for some reason this is inappropriate, you can define BULL_MAILER
+to point to a command procedure, and which will be run instead of VMS MAIL.
+The parameters passed to this procedure are P1 = username and P2 = subject.
+
+1) CREATE.COM
+   This will compile and link the BULLETIN sources. Also, there are several
+   INCLUDE files for the fortran sources (.INC files). BULLETIN will create it's
+   data files in the directory pointed to by the logical name BULL_DIR.  If you
+   elect not to use this definition, BULLFILES.INC should be modified.
+   Note that after this procedure compiles the sources, it puts the objects
+   into an object library, and then deletes all the OBJ files in the directory.
+
+   CREATE.COM will automatically determine if you are running on an alpha
+   rather than a vax and will issue the appropriate commands for that cpu.
+   Of course, separate executables are needed for the two cpus, so if your 
+   site has both, you will have to run this procedure separately on each.
+
+   NOTE 1: If you plan on using the USENET NEWS reader capability of BULLETIN,
+   read NEWS.TXT for installation instructions before compiling.
+
+   NOTE 2: The maximum number of folders for this distribution is 96 folders.
+   If you wish to increase this, modify BULLUSER.INC and recompile the sources.
+   When the new executable is run, it will create a new BULLUSER.DAT data file
+   and rename the old one to BULLUSER.OLD.  You cannot reduce the number of
+   folders.
+
+2) INSTALL.COM
+   The following procedure copies the executable image to BULL_DIR and
+   installs it with certain privileges.  It also installs the necessary
+   help files in SYS$HELP.  (BULLETIN help file is installed into the
+   system help library HELPLIB.HLB.  If you don't wish this done, delete
+   or modify the appropriate line in the procedure.  Also, the help
+   library for the BULLETIN program, BULL.HLB, can be moved to a different
+   directory other than SYS$HELP.  If this is done, the system logical name
+   BULL_HELP should be defined to be the directory where the library is
+   to be found.)
+
+3) LOGIN.COM
+   This contains the commands that should be executed at login time
+   by SYS$MANAGER:SYLOGIN.COM.  It defines the BULLETIN commands.
+   It also executes the command BULLETIN/LOGIN in order to notify
+   the user of new messages.  NOTE: If you wish the utility to be a
+   different name than BULLETIN, you should modify this procedure.
+   The prompt which the utility uses is named after image executable.
+   If you want messages displayed upon logging in starting from
+   oldest to newest (rather than newest to oldest), add /REVERSE to
+   the BULLETIN/LOGIN command.  Note that users with the DISMAIL
+   flag setting in the authorization file will not be notified of
+   new messages.  See help on the SET LOGIN command within the BULLETIN
+   utility for more information on this.  Also, please note that when
+   a brand new user to the system logins, to avoid overwhelming the new
+   user with lots of messages, only PERMANENT SYSTEM messages are displayed.
+
+   If you want SYSTEM messages, i.e. messages which are displayed in full
+   when logging in, to be continually displayed for a period of time rather
+   than just once, you should add the /SYSTEM= qualifier.  This is documented
+   in BULLETIN.HLP, although there it is referred to only with respect to
+   a user wanting to review system messages.  It can be added with /LOGIN.
+
+   DECWINDOWS users should note the following: Both SYLOGIN and LOGIN are
+   executed twice, once before the terminal is actually created, while
+   SYS$OUTPUT is still a mailbox, the other time after the terminal is
+   created.  To avoid this, place the following code in both procedure. 
+   It causes them to execute only when the output is a terminal. This code
+   also helps to allow programs to be placed in LOGIN.COM that prompt for
+   terminal input.  BULLETIN does this if you select READNEW mode for
+   displaying messages when logging in, as READNEW mode will ask you if
+   you want to display the messages text.  Attempts to read terminal input
+   under DECWINDOWS when SYS$OUTPUT is still a mailbox will cause DECTERM
+   creation to fail.  (This problem is fixed under MOTIF).
+
+   $ IF F$LOCATE("_TW",F$GETJPI("","PRCNAM")) .NE. 0 THEN GOTO START
+   $ IF "''F$MODE()'" .NES. "INTERACTIVE" THEN GOTO START
+   $ IF F$GETDVI("SYS$OUTPUT","TRM") THEN GOTO START
+   $ GOTO FINISH
+   $START:
+   .
+   .
+   body of SYLOGIN.COM (including BULLETIN command)
+   .
+   .
+   $FINISH:
+   $ EXIT
+
+4) BULLSTART.COM
+   This procedure contains the commands that should be executed after
+   a system startup.  It should be executed by SYS$MANAGER:SYSTARTUP.COM.
+   It installs the BULLETIN utility with correct privileges.  It also
+   includes the command BULLETIN/STARTUP.  This starts up a detached process
+   with the name BULLCP.  It periodically checks for expire messages,cleanups
+   empty space in files, and converts BBOARD mail to messages.  It also allows
+   other DECNET nodes to share it's folders.  If you don't want this feature
+   and don't plan on having multiple folders or make use of BBOARD, you could
+   eliminate this command if you like.  However, it is highly recommended that
+   you create this process to avoid extra overhead when users login.  NOTE:
+   BULLCP normally is created so it is owned by the DECNET account.  If that
+   account does not exist, BULLCP will be owned by the account that issues
+   the BULLETIN/START command.  In that case, access via other DECNET nodes
+   will not be available.
+
+   If you are installing BULLETIN on a cluster and plan to have the bulletin
+   files be shared between all of the cluster nodes, you only need to have
+   this process running on one node. On all other nodes, the system logical
+   name BULL_BULLCP should be defined (to anything you want) so as to notify
+   BULLETIN that BULLCP is running. (On the local node where BULLCP is running,
+   this logical name is automatically defined.)
+
+   The system logical name BULL_CUSTOM can be defined to enable several 
+   features.  It is equated to a hex number string.  
+	Bit 0 set = need privileges to create folder.
+	    1 set = captive account can write files.
+	    2 set = captive account can use editor. 
+   
+   If you want to have more than one database, you can do so by redefining 
+   BULL_DIR to another directory.  However, only directories that are 
+   defined in the list of equivalence names pointed to by the system logical 
+   name BULL_DIR_LIST are allowed.  For example:
+
+	DEFINE/SYSTEM BULL_DIR_LIST SITE$ROOT:[SYSEXE],USER1:[MRL]
+
+   Then BULL_DIR can be defined as SITE$ROOT:[SYSEXE] or USER1:[MRL].  
+   BULL_DIR_LIST must be defined on all nodes in a cluster.
+   
+   The use of the MARK command to mark messages require that a file be
+   created for each user which saves the marked info.  That file file is
+   stored in the directory pointed to by the logical name BULL_MARK.  You can
+   either let users who want to use this command define it themselves, or
+   you can define it for them, i.e. DEFINE/SYSTEM BULL_MARK SYS$LOGIN.
+
+5) INSTRUCT.COM
+   This procedure adds 2 permanent messages which give a very brief
+   description about the BULLETIN utility, and how to turn off optional
+   prompting of non-system messages (via SET NOREADNEW).
+
+6) BOARD_SPECIAL.COM
+   This command procedure describes and illustrates how to use the
+   SET BBOARD/SPECIAL feature.  This feature allows the use of BBOARD
+   where the input does not come from VMS MAIL.  For example, this could
+   be used in the case where mail from a non-DEC network is not stored
+   in the VMS MAIL.  Another example is BOARD_DIGEST.COM.  This file
+   takes mail messages from "digest" type mailing lists and splits them
+   into separate BULLETIN messages for easier reading.
+
+   To use this feature, place the special command procedure into the
+   bulletin file directory using the name BOARD_SPECIAL.COM.  If you want
+   to have several different special procedure, you should name the command
+   procedure after the username specified by the SET BBOARD command.
+
+7) UPGRADE.COM
+   This procedure is used to upgrade to a new version of BULLETIN.
+   See comments for instructions.
+
+8) MASTER.COM
+   If you are using PMDF, and want to use the BBOARD option, a set of
+   routines are included which will allow PMDF to write message directly
+   into folders, which is a much more effecient way of doing it than
+   the normal BBOARD method of using VMS MAIL.  Read PMDF.TXT for how
+   to do this.
+
+9) OPTIMIZE_RMS.COM
+   This routine optimizes index files.  To run, type @OPTIMIZE_RMS.COM
+   followed by the filename.  If you omit the filename, it will prompt
+   you to allow you to turn off or on several different types of RMS
+   compression.  The default is to turn on all types of compression.
+   The optimization will cause the file to be compressed.
+
+   If you use the NEWS feature, it is suggest that you run this procedure
+   on BULLNEWS.DAT after it is created.  Compressing that file greatly speeds
+   up the NEWS update process.  If you are tight on space, and have been
+   running BULLETIN for a long time, it might also be useful to compress
+   BULLINF.DAT if that file is very large.  However, compressing that (or
+   the other BULLETIN data files) don't appear to save any execution time,
+   unlike BULLNEWS.DAT.
diff --git a/decus/vmslt00a/bulletin/aaareadme.txt b/decus/vmslt00a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6d65febce52e84e7adfd6efbeb5edbc3af4153c5
Binary files /dev/null and b/decus/vmslt00a/bulletin/aaareadme.txt differ
diff --git a/decus/vmslt00a/bulletin/allmacs.mar b/decus/vmslt00a/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..3725b8ad2b7e36926f562ac80706e31797db99ae
--- /dev/null
+++ b/decus/vmslt00a/bulletin/allmacs.mar
@@ -0,0 +1,312 @@
+;
+;  Name: SETACC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the account name of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETACC(account)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	account		- Character string containing account name
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETACC
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+
+	.PSECT	 DATA,NOEXE
+
+NEWACC:	.BLKB	12				; Contains new account name
+;
+;  Executable:
+;
+	.PSECT	CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETACC,^M<R2,R3,R4,R5,R6,R7>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R6				; Get number of arguments
+	CMPL	R6,#1				; Correct number of arguments?
+	BNEQ	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#8,NEWACC		; Get new account name string
+	$CMKRNL_S ROUTIN=SETACC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY	SETACC_C,^M<R2,R3,R4,R5,R6>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R6			; Address of current process
+	MOVL	PCB$L_JIB(R6),R6		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R6		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#8,NEWACC,JIB$T_ACCOUNT(R6) 	; change account JIB
+	MOVC3	#8,NEWACC,CTL$T_ACCOUNT 	; change account in P1
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUIC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: May 31, 1983
+;
+;  Purpose: To set the UIC of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUIC(group number, user number)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	group number	- longword containing UIC group number
+;	user number	- longword containing UIC user number
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUIC	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+
+	.PSECT	 SETUIC_DATA,NOEXE
+
+UIC:	.BLKL	1
+;
+;  Executable:
+;
+	.PSECT	SETUIC_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY SETUIC,^M<R2,R3>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R2				; Get number of arguments
+	CMPL	R2,#2				; Are there 2 arguments
+	BNEQ	5$				; If not, return
+	MOVL	@4(AP),R3			; Group number into R3
+	ROTL	#16,R3,R3			; Move to upper half of R3
+	ADDL2	@8(AP),R3			; User number to top half of R3
+	MOVL	R3,UIC
+	$CMKRNL_S ROUTIN=SETUIC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY SETUIC_C,^M<R4>			; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R2			; Address of current process
+	MOVL	UIC,PCB$L_UIC(R2)		; Set UIC to specified
+;	MOVL	UIC,PCB$L_UIC(R4)		; Set UIC to specified
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUSER.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the Username of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUSER(username)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	username	- Character string containing username
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUSER	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+	.PSECT	 SETUSER_DATA,NOEXE
+
+NEWUSE:	.BLKB	12				; Contains new username
+OLDUSE: .BLKB	12				; Contains old username
+OLDLEN: .BLKW   1
+;
+;  Executable:
+;
+	.PSECT	SETUSER_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETUSER,^M<R2,R3,R4,R5,R6,R7,R8>        
+	CLRL	R0				; 0 is error code 
+	MOVZBL	(AP),R8				; Get number of arguments
+	CMPL	R8,#1				; Correct number of arguments
+	BLSS	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,NEWUSE		; Get new username string
+	CMPL	R8,#2				; Old username given?
+	BLSS	2$				; No
+	MOVZBL	@8(AP),R6			; Get size of string
+	MOVL	8(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,OLDUSE		; Get old username string
+        MOVL	R6,OLDLEN
+	$CMKRNL_S ROUTIN=SETUSER_C2		; Must run in kernel mode
+	TSTL	R0				; If old username is checks with
+   	BEQL	2$				; present process name, change
+	MOVL	#2,R0				; to new username, else flag
+	RET					; error and return
+2$:	$CMKRNL_S ROUTIN=SETUSER_C1		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY  SETUSER_C1,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#12,NEWUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	MOVC3	#12,NEWUSE,CTL$T_USERNAME 	; change username in P1    
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+
+	.ENTRY  SETUSER_C2,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: CMPC destroys r0-r5
+	CMPC	OLDLEN,OLDUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	RET
+
+	.SBTTL	KMODE error handler
+
+; This error handler should prevent those embarrasing crashes when you woof
+; in kernel mode.  It doesn't try to fix anything, it just unwinds the stack
+; and saves the error signal status.  Good for little things like division
+; by zero or access violations etc.  If you destroy an important system data
+; structure this handler wont be able to fix it and the system will eventually
+; crash.
+;
+; Written by Anthony C. McCracken, Northern Arizona University.
+; 25-SEP-1992
+;
+; I was tired of rebooting the machine after silly coding errors.  :)
+;
+	.ENTRY	KMODE_EHAND,^M<R5,R6>
+	MOVL	4(AP),R5		; Get the signal array
+	CMPL	4(R5),#SS$_UNWIND
+	BNEQ	10$			; Just return if were already
+	RET				; unwinding
+10$:	MOVL	8(AP),R6		; Get the mechanism array
+	MOVL	4(R5),12(R6)		; Stash the error code
+	$UNWIND_S			; and unwind back out
+	RET
+
+
+	.TITLE	READ_HEADER - Read Image Header
+	.IDENT	/1-001/
+
+; This subroutine returns the image identification and link time.
+;
+; Format:
+;
+;   status.wlc.v = READ_HEADER( ident.wt.ds [,time.wt.ds] )
+;
+; Parameters:
+;
+;   ident	The image identification text.
+;
+;   time	The image link time (text format).
+
+
+;   Date	By		Comments
+;  4/10/87	D.E. Greenwood	Originally written by John Miano, 24-June-1986 -
+;				obtained from April 87 DECUS L&T Sig Newsletter
+	.LIBRARY	"SYS$LIBRARY:LIB"
+
+	$DSCDEF
+	$IHDDEF
+	$IHIDEF
+	$SSDEF
+
+; Argument pointer offsets
+
+	$OFFSET 4,POSITIVE,<IDENT,TIME>
+
+	.PSECT READ_HEADER, RD, NOWRT, EXE, LONG
+	.ENTRY READ_HEADER, ^M< R2, R3, R4, R5, R6, R7, R8, R11 >
+
+	CMPL	(AP),#1 		; Make sure that there is at least
+	BGEQ	ENOUGH_ARGUMENTS	;  one argument to this routine
+	MOVL	#SS$_INSFARG, R0
+	RET
+
+ENOUGH_ARGUMENTS:
+
+; Get the identification of the image.
+
+	MOVL	@#CTL$GL_IMGHDRBF, R11	; R11 - Address of image buffer
+	MOVL	(R11), R6		; R6  - Address of image header
+
+	CVTWL	IHD$W_IMGIDOFF(R6), R7
+	MOVAB	(R6)[R7], R7		; R7 - Address of ID Block
+
+	CVTBL	IHI$T_IMGID(R7),R0	; Length of the ID string
+	MOVL	IDENT(AP), R8
+	MOVC5	R0, <IHI$T_IMGID+1>(R7), #32, -
+		DSC$W_LENGTH(R8), @DSC$A_POINTER(R8)
+
+	CMPL	(AP), #2
+	BGEQ	RETURN_TIME
+	MOVZBL	#1, R0
+	RET
+
+RETURN_TIME:
+
+; Get the time the image was linked and convert it to ASCII
+
+	$ASCTIM_S -
+		TIMBUF=@TIME(AP), -
+		TIMADR=IHI$Q_LINKTIME(R7)
+
+	RET
+
+.END
diff --git a/decus/vmslt00a/bulletin/allmacs_axp.mar b/decus/vmslt00a/bulletin/allmacs_axp.mar
new file mode 100755
index 0000000000000000000000000000000000000000..fb06e99cfeb522d26fb3c7c7f2b53d485d896958
--- /dev/null
+++ b/decus/vmslt00a/bulletin/allmacs_axp.mar
@@ -0,0 +1,312 @@
+;
+;  Name: SETACC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the account name of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETACC(account)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	account		- Character string containing account name
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETACC
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+
+	.PSECT	 DATA,NOEXE
+
+NEWACC:	.BLKB	12				; Contains new account name
+;
+;  Executable:
+;
+	.PSECT	CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETACC,^M<R2,R3,R4,R5,R6,R7>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R6				; Get number of arguments
+	CMPL	R6,#1				; Correct number of arguments?
+	BNEQ	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#8,NEWACC		; Get new account name string
+	$CMKRNL_S ROUTIN=SETACC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY	SETACC_C,^M<R2,R3,R4,R5,R6>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R6			; Address of current process
+	MOVL	PCB$L_JIB(R6),R6		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R6		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#8,NEWACC,JIB$T_ACCOUNT(R6) 	; change account JIB
+	MOVC3	#8,NEWACC,CTL$T_ACCOUNT 	; change account in P1
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUIC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: May 31, 1983
+;
+;  Purpose: To set the UIC of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUIC(group number, user number)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	group number	- longword containing UIC group number
+;	user number	- longword containing UIC user number
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUIC	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+
+	.PSECT	 SETUIC_DATA,NOEXE
+
+UIC:	.BLKL	1
+;
+;  Executable:
+;
+	.PSECT	SETUIC_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY SETUIC,^M<R2,R3>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R2				; Get number of arguments
+	CMPL	R2,#2				; Are there 2 arguments
+	BNEQ	5$				; If not, return
+	MOVL	@4(AP),R3			; Group number into R3
+	ROTL	#16,R3,R3			; Move to upper half of R3
+	ADDL2	@8(AP),R3			; User number to top half of R3
+	MOVL	R3,UIC
+	$CMKRNL_S ROUTIN=SETUIC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY SETUIC_C,^M<R4>			; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R2			; Address of current process
+	MOVL	UIC,PCB$L_UIC(R2)		; Set UIC to specified
+;	MOVL	UIC,PCB$L_UIC(R4)		; Set UIC to specified
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUSER.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the Username of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUSER(username)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	username	- Character string containing username
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUSER	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+	.PSECT	 SETUSER_DATA,NOEXE
+
+NEWUSE:	.BLKB	12				; Contains new username
+OLDUSE: .BLKB	12				; Contains old username
+OLDLEN: .BLKW   1
+;
+;  Executable:
+;
+	.PSECT	SETUSER_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETUSER,^M<R2,R3,R4,R5,R6,R7,R8>        
+	CLRL	R0				; 0 is error code 
+	MOVZBL	(AP),R8				; Get number of arguments
+	CMPL	R8,#1				; Correct number of arguments
+	BLSS	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,NEWUSE		; Get new username string
+	CMPL	R8,#2				; Old username given?
+	BLSS	2$				; No
+	MOVZBL	@8(AP),R6			; Get size of string
+	MOVL	8(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,OLDUSE		; Get old username string
+        MOVL	R6,OLDLEN
+	$CMKRNL_S ROUTIN=SETUSER_C2		; Must run in kernel mode
+	TSTL	R0				; If old username is checks with
+   	BEQL	2$				; present process name, change
+	MOVL	#2,R0				; to new username, else flag
+	RET					; error and return
+2$:	$CMKRNL_S ROUTIN=SETUSER_C1		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY  SETUSER_C1,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#12,NEWUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	MOVC3	#12,NEWUSE,CTL$T_USERNAME 	; change username in P1    
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+
+	.ENTRY  SETUSER_C2,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: CMPC destroys r0-r5
+	CMPC	OLDLEN,OLDUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	RET
+
+	.SBTTL	KMODE error handler
+
+; This error handler should prevent those embarrasing crashes when you woof
+; in kernel mode.  It doesn't try to fix anything, it just unwinds the stack
+; and saves the error signal status.  Good for little things like division
+; by zero or access violations etc.  If you destroy an important system data
+; structure this handler wont be able to fix it and the system will eventually
+; crash.
+;
+; Written by Anthony C. McCracken, Northern Arizona University.
+; 25-SEP-1992
+;
+; I was tired of rebooting the machine after silly coding errors.  :)
+;
+	.ENTRY	KMODE_EHAND,^M<R5,R6>
+	MOVL	4(AP),R5		; Get the signal array
+	CMPL	4(R5),#SS$_UNWIND
+	BNEQ	10$			; Just return if were already
+	RET				; unwinding
+10$:	MOVL	8(AP),R6		; Get the mechanism array
+	MOVL	4(R5),12(R6)		; Stash the error code
+	$UNWIND_S			; and unwind back out
+	RET
+
+
+	.TITLE	READ_HEADER - Read Image Header
+	.IDENT	/1-001/
+
+; This subroutine returns the image identification and link time.
+;
+; Format:
+;
+;   status.wlc.v = READ_HEADER( ident.wt.ds [,time.wt.ds] )
+;
+; Parameters:
+;
+;   ident	The image identification text.
+;
+;   time	The image link time (text format).
+
+
+;   Date	By		Comments
+;  4/10/87	D.E. Greenwood	Originally written by John Miano, 24-June-1986 -
+;				obtained from April 87 DECUS L&T Sig Newsletter
+	.LIBRARY	"SYS$LIBRARY:LIB"
+
+	$DSCDEF
+	$EIHDDEF
+	$EIHIDEF
+	$SSDEF
+
+; Argument pointer offsets
+
+	$OFFSET 4,POSITIVE,<IDENT,TIME>
+
+	.PSECT READ_HEADER, RD, NOWRT, EXE, LONG
+	.ENTRY READ_HEADER, ^M< R2, R3, R4, R5, R6, R7, R8, R11 >
+
+	CMPL	(AP),#1 		; Make sure that there is at least
+	BGEQ	ENOUGH_ARGUMENTS	;  one argument to this routine
+	MOVL	#SS$_INSFARG, R0
+	RET
+
+ENOUGH_ARGUMENTS:
+
+; Get the identification of the image.
+
+	MOVL	@#CTL$GL_IMGHDRBF, R11	; R11 - Address of image buffer
+	MOVL	(R11), R6		; R6  - Address of image header
+
+	MOVL	EIHD$L_IMGIDOFF(R6), R7
+	MOVAB	(R6)[R7], R7		; R7 - Address of ID Block
+
+	CVTBL	EIHI$T_IMGID(R7),R0	; Length of the ID string
+	MOVL	IDENT(AP), R8
+	MOVC5	R0, <EIHI$T_IMGID+1>(R7), #32, -
+		DSC$W_LENGTH(R8), @DSC$A_POINTER(R8)
+
+	CMPL	(AP), #2
+	BGEQ	RETURN_TIME
+	MOVZBL	#1, R0
+	RET
+
+RETURN_TIME:
+
+; Get the time the image was linked and convert it to ASCII
+
+	$ASCTIM_S -
+		TIMBUF=@TIME(AP), -
+		TIMADR=EIHI$Q_LINKTIME(R7)
+
+	RET
+
+.END
diff --git a/decus/vmslt00a/bulletin/board_digest.com b/decus/vmslt00a/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..dec53c189229960499c10127241c1cd8cebb2239
--- /dev/null
+++ b/decus/vmslt00a/bulletin/board_digest.com
@@ -0,0 +1,77 @@
+$!
+$! BOARD_DIGEST.COM
+$!
+$! Command file invoked by folder associated with a BBOARD which is
+$! is specified with /SPECIAL.  It will convert "digest" mail and
+$! split it into separate messages.  This type of mail is used in
+$! certain Arpanet mailing lists, such as TEXHAX and INFO-MAC.
+$!
+$ FF[0,8] = 12			! Define a form feed character
+$ SET PROTECT=(W:RWED)/DEFAULT
+$ SET PROC/PRIV=SYSPRV
+$ USER := 'F$GETJPI("","USERNAME")
+$ EXTRACT_FILE = "BULL_DIR:" + "''USER'" + ".TXT"
+$ DEFINE/USER EXTRACT_FILE BULL_DIR:'USER'
+$ MAIL
+READ
+EXTRACT EXTRACT_FILE
+DELETE
+$ OPEN/READ INPUT 'EXTRACT_FILE'
+$ OPEN/WRITE OUTPUT 'EXTRACT_FILE'
+$ READ INPUT FROM_USER
+$AGAIN:
+$ READ/END=ERROR INPUT BUFFER
+$ IF F$EXTRACT(0,3,BUFFER) .NES. "To:" THEN GOTO SKIP
+$ USER = F$EXTRACT(4,F$LEN(BUFFER),BUFFER)
+$ GOTO AGAIN1
+$SKIP:
+$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN
+$AGAIN1:
+$ READ/END=ERROR INPUT BUFFER
+$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN1
+$ FROM = " "
+$ SUBJ = " "
+$NEXT:
+$ READ/END=EXIT INPUT BUFFER
+$FROM:
+$ IF F$EXTRACT(0,5,BUFFER) .NES. "From:" THEN GOTO SUBJECT
+$ FROM = BUFFER 
+$ GOTO NEXT
+$SUBJECT:
+$ IF F$EXTRACT(0,8,BUFFER) .NES. "Subject:" THEN GOTO NEXT
+$ SUBJ = BUFFER - "Subject:"
+$F2:
+$ IF F$LENGTH(SUBJ) .EQ. 0 THEN GOTO WRITE
+$ IF F$EXTRACT(0,1,SUBJ) .NES. " " THEN GOTO WRITE
+$ SUBJ = F$EXTRACT(1,F$LENGTH(SUBJ),SUBJ)
+$ GOTO F2
+$WRITE:
+$ WRITE OUTPUT FROM_USER
+				! Write From: + TAB + USERNAME
+$ WRITE OUTPUT "To:	" + USER
+				! Write To: + TAB + BBOARDUSERNAME
+$ WRITE OUTPUT "Subj:	" + SUBJ
+				! Write Subject: + TAB + mail subject
+$ WRITE OUTPUT ""		! Write one blank line
+$ IF FROM .NES. " " THEN WRITE OUTPUT FROM
+$READ:
+$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
+$ IF F$EXTRACT(0,15,BUFFER) .EQS. "---------------" THEN GOTO READ1
+$ WRITE OUTPUT BUFFER
+$ GOTO READ
+$READ1:
+$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
+$ IF F$LOCATE(":",BUFFER) .EQ. F$LENGTH(BUFFER) THEN GOTO READ1
+$ WRITE OUTPUT FF
+$ FROM = " "
+$ SUBJ = " "
+$ GOTO FROM
+$EXIT:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ PUR 'EXTRACT_FILE'
+$ EXIT
+$ERROR:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ DELETE 'EXTRACT_FILE';
diff --git a/decus/vmslt00a/bulletin/board_special.com b/decus/vmslt00a/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..93e16c3d9c42b59f57f99ca6e5e454e1ea380cec
--- /dev/null
+++ b/decus/vmslt00a/bulletin/board_special.com
@@ -0,0 +1,108 @@
+$!
+$! BOARD_SPECIAL.COM
+$!
+$! Command file invoked by folder associated with a BBOARD which is
+$! is specified with /SPECIAL.  This can be used to convert data to
+$! a message via a different means than the VMS mail.  This is done by
+$! converting the data to look like output created by the MAIL utility,
+$! which appears as follows:
+$!
+$!	First line is 0 length line.
+$!	Second line is "From:" followed by TAB followed by incoming username
+$!	Third line is "To:" followed by TAB followed by BBOARD username
+$!	Fourth line is "Subj:" followed by TAB followed by subject
+$!	The message text then follows.
+$!	Message is ended by a line containing a FORM FEED.
+$!
+$! This command file should be put in the BBOARD_DIRECTORY as specified
+$! in BULLFILES.INC.  You can also have several different types of special
+$! procedures.  To accomplish this, rename the file to the BBOARD username.
+$! i.e. if you specify SET BBOARD FOO/SPECIAL, you could name the file
+$! FOO.COM and it will execute that rather than BOARD_SPECIAL.COM.
+$!
+$! The following routine is the one we use to convert mail from a non-DEC
+$! mail network.  The output from this mail is written into a file which
+$! is slightly different from the type outputted by MAIL.
+$!
+$! (NOTE: A username in the SET BBOARD command need only be specified if
+$! the process which reads the mail requires that the process be owned by
+$! a specific user, which is the case for this sample, and for that matter
+$! when reading VMS MAIL.  If this is not required, you do not have to
+$! specify a username.)
+$!
+$ USERNAME := 'F$GETJPI("","USERNAME")'		! This trims trailing spaces
+$ IF F$SEARCH("MFE_TELL_FILES:"+USERNAME+".MAI") .EQS. "" THEN EXIT
+$ SET DEFAULT BULL_DIR:	! BULLETIN looks for text in BBOARD directory
+$ SET PROTECT=(W:RWED)/DEFAULT
+$ IF F$SEARCH("MFEMSG.MAI") .NES. "" THEN -
+  DELETE MFEMSG.MAI;*		! Delete any leftover output files.
+$ MSG := $MFE_TELL: MESSAGE
+$ DEFINE/USER SYS$COMMAND SYS$INPUT
+$ MSG				! Read MFENET mail
+copy * MFEMSG
+delete *
+exit
+$ FF[0,8] = 12			! Define a form feed character
+$ OPEN/READ/ERROR=EXIT INPUT MFEMSG.MAI
+$ OUTNAME = USERNAME+".TXT"	! Output file will be 'USERNAME'.TXT
+$ OPEN/WRITE OUTPUT 'OUTNAME'
+$ READ/END=END INPUT DATA		! Skip first line in MSG output
+$HEADER:
+$ FROM = ""
+$ SUBJ = ""
+$ MFEMAIL = "T"
+$NEXTHEADER:
+$ IF (FROM.NES."") .AND. (SUBJ.NES."") THEN GOTO SKIPHEADER
+$ READ/END=END INPUT DATA		! Read header line in MSG output
+$ IF DATA .EQS. "" THEN GOTO SKIPHEADER	! Missing From or Subj ??
+$ IF FROM .NES. "" THEN GOTO SKIPFROM
+$ IF F$LOCATE("From: ",DATA) .NES. 0 THEN GOTO 10$
+$ MFEMAIL = "F"
+$ FROM= F$EXTRACT(6,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$10$:
+$ IF F$LOCATE("Reply-to: ",DATA) .NES. 0 THEN GOTO 20$
+$ MFEMAIL = "F"
+$ FROM= F$EXTRACT(10,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$20$:
+$ IF F$LOCATE("From ",DATA) .NES. 0 THEN GOTO SKIPFROM
+$ FROM= F$EXTRACT(5,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$SKIPFROM:
+$ IF SUBJ .NES. "" THEN GOTO SKIPSUBJ
+$ IF F$LOCATE("Subject",DATA) .NES. 0 THEN GOTO SKIPSUBJ
+$ SUBJ= F$EXTRACT(F$LOCATE(": ",DATA)+2,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$SKIPSUBJ:
+$ GOTO NEXTHEADER
+$SKIPHEADER:
+$ WRITE OUTPUT "From:	" + FROM
+				! Write From: + TAB + USERNAME
+$ WRITE OUTPUT "To:	" + USERNAME
+				! Write To: + TAB + BBOARDUSERNAME
+$ WRITE OUTPUT "Subj:	" + SUBJ
+				! Write Subject: + TAB + mail subject
+$ WRITE OUTPUT ""		! Write one blank line
+$ IF (DATA.EQS."") .OR. MFEMAIL THEN GOTO SKIPBLANKS
+$50$:
+$ READ/END=END INPUT DATA		! Skip rest of main header
+$ IF DATA .NES. "" THEN GOTO 50$
+$60$:
+$ READ/END=END INPUT DATA		! Skip all of secondary header
+$ IF DATA .NES. "" THEN GOTO 60$
+$SKIPBLANKS:
+$ READ/END=END INPUT DATA		! Skip all blanks
+$ IF DATA .EQS. "" THEN GOTO SKIPBLANKS
+$NEXT:				! Read and write message text
+$ WRITE OUTPUT DATA
+$ IF DATA .EQS. FF THEN GOTO HEADER
+			! Multiple messages are seperated by form feeds
+$ READ/END=END INPUT DATA
+$ GOTO NEXT
+$END:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ DELETE MFEMSG.MAI;
+$EXIT:
+$ EXIT
diff --git a/decus/vmslt00a/bulletin/bull_news.c b/decus/vmslt00a/bulletin/bull_news.c
new file mode 100755
index 0000000000000000000000000000000000000000..177fef6b4dc8d12022fb9fb7981c8d3b5cdd7173
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bull_news.c
@@ -0,0 +1,934 @@
+#include <string.h>
+#include <descrip.h>
+#include <stdio.h>
+#include "sys$library:iodef.h"
+
+#if MULTINET
+
+#include "multinet_root:[multinet.include.sys]types.h"
+#include "multinet_root:[multinet.include.sys]socket.h"
+#include "multinet_root:[multinet.include.netinet]in.h"
+#include "multinet_root:[multinet.include.arpa]inet.h"
+#include "multinet_root:[multinet.include]netdb.h"
+#include "multinet_root:[multinet.include]errno.h"
+#include "multinet_root:[multinet.include.vms]inetiodef.h"
+
+static char inet[7] = "INET0:";
+$DESCRIPTOR(inet_d,inet);
+
+static struct dns {
+	unsigned char function;
+	unsigned char call_code;
+	short zeros;
+	short length;
+	char string[512];
+} buf1, buf2;
+
+struct  sockaddr_un {
+        short   sun_family;             /* AF_UNIX */
+        char    sun_path[109];          /* path name (gag) */
+};
+#else
+
+#if UCX
+
+#include <ucx$inetdef.h>
+
+struct sockaddr {
+  short inet_family;
+  short inet_port;
+  int inet_adrs;
+  char bklb[8];
+  };
+
+struct itlist { int lgth; struct sockaddr *hst; };
+
+static short sck_parm[2];
+static struct sockaddr local_host, remote_host;
+struct itlist lhst_adrs, rhst_adrs;
+
+static char ucxdev[11] = "UCX$DEVICE";
+$DESCRIPTOR(ucxdev_d,ucxdev);
+
+static int addr_buff;
+
+#define htons(x) ((unsigned short)((x<<8)|(x>>8)))
+
+#else
+
+#if TWG
+
+#include <types.h>
+#include <socket.h>
+#include <netdb.h>
+#include <in.h>
+#include <inetiodef.h>
+
+static char inet[6] = "INET:";
+$DESCRIPTOR(inet_d,inet);
+
+#else
+
+#define CMU 1
+static char ip[4] = "IP:";
+$DESCRIPTOR(ip_d,ip);
+
+#endif
+
+#endif
+
+#endif
+
+static char task[20];
+$DESCRIPTOR(task_d,task);
+
+static int s,s1;
+
+static struct iosb {
+	short status;
+	short size;
+	int info;
+} iosb;
+
+#define TCP 0
+#define DECNET 1
+
+static int mode = TCP;
+
+#if MULTINET
+
+#include <lib$routines>
+#include <stdarg.h>
+#ifdef __ALPHA
+unsigned int __VA_COUNT_BUILTIN(void);
+#define va_count(count)		(count = __VA_COUNT_BUILTIN())
+#else
+#ifdef VAXC
+#define va_count(n) vaxc$va_count(&n)
+extern int vaxc$va_count();
+#else
+#define va_count(n) decc$va_count(&n)
+extern int decc$va_count();
+#endif
+#endif
+
+static int FindRoutine(struct dsc$descriptor *image,
+		       struct dsc$descriptor *routine, int (**rtn)());
+
+int inet_ntoa1(int *arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"inet_ntoa");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = *arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int gethostname1(int arg1,int arg2)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"gethostname");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int htons1(int arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"htons");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int gethostbyname1(int arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"gethostbyname");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+static int FindRoutine(struct dsc$descriptor *image,
+		       struct dsc$descriptor *routine, int (**rtn)())
+{
+  lib$establish(lib$sig_to_ret);
+  return lib$find_image_symbol(image,routine,rtn);
+}
+#endif
+
+news_get_chan()
+{return(s);}
+
+news_set_chan(i)
+int *i;
+{s = *i;}
+
+news_disconnect()
+{
+#if UCX
+	sys$cancel(s);
+	sys$qiow(0,s,IO$_DEACCESS,0,0,0,0,0,0,0,0,0);
+#endif
+	sys$dassgn(s);
+}
+
+#if MULTINET || TWG
+
+static struct hostent *hp, *hp1;
+static struct sockaddr_in sin;
+
+#endif
+
+int *node,*node1;
+
+news_gethost()
+{
+	/*
+	 *  Get the IP address of the NEWS host.
+	 *  As of MULTINET 3.0, cannot be done at AST level
+	 *  so can't do in NEWS_ASSIGN(), as BULLCP calls it at
+	 *  AST level if the decnet gateway feature is used.
+	 */
+#if TWG
+	struct hostent *gethostbyname();
+#else
+#if MULTINET
+#endif
+#endif
+
+	node = getenv("BULL_NEWS_SERVER");
+	if (!node) return(0);
+	if (!strchr(node,'.')) return(1); 
+
+#if TWG
+	hp = gethostbyname(node);
+#else
+#if MULTINET
+	hp = gethostbyname1(node);
+#endif
+#endif
+	return(1);
+}
+
+news_assign()
+{
+	int n;
+
+	if (!strchr(node,'.')) {
+	   strcpy(&task[0],node);
+	   n = strlen(node);
+	   strcpy(&task[n],"::\"TASK=NNTP\"");
+	   task_d.dsc$w_length = 13 + n;
+	   if (!(sys$assign(&task_d,&s,0,0) & 1)) return(0);
+	   mode = DECNET;
+	   return(1);
+	}
+#if MULTINET || TWG
+	/*
+	 *  Create a "sockaddr_in" structure which describes the remote
+	 *  IP address we want to send to (from gethostbyname()).
+	 */
+
+        if (!hp) {
+          int h[4],i;
+          if (sscanf(node,"%d.%d.%d.%d",&h[0],&h[1],&h[2],&h[3]) == 4) {
+            for (i=0;i<4;i++) if (h[i] < 0 || h[i] > 255) return(0);
+	    sin.sin_addr.s_addr = (h[3]<<24)+(h[2]<<16)+(h[1]<<8)+(h[0]);
+	  } else
+	    return(0);
+	  sin.sin_family = AF_INET;
+	}
+        else {
+ 	  sin.sin_family = hp->h_addrtype;
+	  memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
+        }
+#if TWG
+	sin.sin_port = htons(119);
+#else
+	sin.sin_port = htons1(119);
+#endif
+
+	/*
+	 *  Create an IP-family socket on which to make the connection
+	 */
+
+	if (!(sys$assign(&inet_d,&s,0,0) & 1)) return(0);
+#else
+#if UCX
+         if (!(sys$assign(&ucxdev_d,&s,0,0) & 1)) return(0);
+	{
+           short retlen;
+	   struct dsc$descriptor host_name
+		= {strlen(node),DSC$K_CLASS_S,DSC$K_DTYPE_T,node};
+	   int comm = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYNAME;
+	   struct dsc$descriptor command
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&comm};
+	   struct dsc$descriptor host_ad
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&addr_buff};
+	   struct iosb nam_iosb;
+
+           if (!(sys$qiow(0,s,IO$_ACPCONTROL,&nam_iosb,0,0,
+                       &command,&host_name,&retlen,&host_ad,0,0) & 1)
+               || !(nam_iosb.status & 1)) {
+              sys$dassgn(s);
+	      return(0);
+	   }
+	}
+#else
+	if (!(sys$assign(&ip_d,&s,0,0) & 1)) return(0);
+#endif
+#endif
+	return(1);
+}
+
+struct iosb accept_iosb;
+
+nntp_listen(listen_chan)
+int *listen_chan;
+{
+#if MULTINET
+	struct sockaddr_in sin;
+	struct iosb accept_iosb;
+
+	if (!(sys$assign(&inet_d,listen_chan,0,0) & 1)) return(0);
+
+	/*
+	 *  Create an IP-family socket on which to listen for connections
+	 */
+	if (!(sys$qiow(0,*listen_chan,IO$_SOCKET,&accept_iosb,0,0,AF_INET,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	/*
+	 *  Create a "sockaddr_in" structure which describes the port we
+	 *  want to listen to. Address INADDR_ANY means we will accept
+	 *  connections to any of our local IP addresses.
+	 */
+
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = INADDR_ANY;
+	sin.sin_port = htons1(119);
+
+	/*
+	 *  Bind to that address...
+	 */
+
+	if (!(sys$qiow(0,*listen_chan,IO$_BIND,&accept_iosb,0,0,
+	   &sin,sizeof(sin),0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+ 	/*
+	 *  Declare to the kernel that we want to listen for connections
+	 *  on this port, and that the kernel may queue up to five such
+	 *  connections for us.
+	 */
+
+	if (!(sys$qiow(0,*listen_chan,IO$_LISTEN,&accept_iosb,0,0,5,
+	    0,0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	return(1);
+#else
+	return(0);
+#endif
+}
+
+nntp_accept_wait(listen_chan,listen_ast,listen_iosb)
+int *listen_chan,*listen_ast,*listen_iosb;
+{
+#if MULTINET                                            
+	if (!(sys$qio(0,*listen_chan,IO$_ACCEPT_WAIT,listen_iosb,listen_ast,
+	    0,0,0,0,0,0,0) & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	return(1);
+#endif
+}
+ 
+nntp_accept(listen_chan,accept_chan,accept_iosb)
+int *listen_chan,*accept_chan;
+struct iosb *accept_iosb;
+{
+#if MULTINET
+	struct sockaddr_in sin;
+	FILE *fp;
+	char buf[128];
+	char *cp, *h;
+	int s;
+	struct sockaddr_un sun = {AF_UNIX};
+
+	*accept_chan = -1;
+
+	    /*
+	     *	Call accept to accept a new connection. This 'peels'
+	     *	a connection off of the original socket and returns to us
+	     *	a new channel to the connection. We could now close
+	     *	down the original socket if we didn't want to handle
+	     *	more connections.
+	     */
+	if (!(sys$assign(&inet_d,accept_chan,0,0) & 1)) return(0);
+
+	if (!(sys$qiow(0,*accept_chan,IO$_ACCEPT,accept_iosb,0,0,
+	   &sin,sizeof(sin),*listen_chan,0,0,0) & 1)
+	   || !(accept_iosb->status & 1)) return(0);
+
+	fp = fopen("BULL_TCP_NEWS_GATEWAY", "r");
+	if (!fp) return(1);
+
+	/* A non-official way of getting ip name at ast level */
+
+	if (!(sys$assign(&inet_d,&s,0,0) & 1)) return(0);
+	if (!(sys$qiow(0,s,IO$_SOCKET,&iosb,0,0,AF_UNIX,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1))
+	    {printf("1 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	strcpy(sun.sun_path,"DNS");
+	if (!(sys$qiow(0,s,IO$_CONNECT,&iosb,0,0,&sun,sizeof(sun),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("2 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+/*	buf1.function = 1;	/* gethostbyname */
+	buf1.function = 2;	/* gethostbyaddr */
+	buf1.call_code = 0;
+	buf1.length = strlen(inet_ntoa1((int)(&sin.sin_addr)));
+ 	strcpy(buf1.string,inet_ntoa1((int)(&sin.sin_addr)));
+
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,&buf1,
+					sizeof(buf1),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("3 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	if (!(sys$qiow(0,s,IO$_READVBLK,&iosb,0,0,&buf2,
+					sizeof(buf2),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("4 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	printf("5 iosb.status = %d\n",iosb.status);sys$dassgn(s);
+	buf2.string[buf2.length] = 0;
+	for (cp=buf2.string; *cp; cp++) *cp = tolower(*cp);
+
+	while (fgets(buf, sizeof(buf), fp)) {
+	    for (cp=buf; *cp != '\n'; cp++) *cp = tolower(*cp);
+	    *cp = 0;
+	    for (cp=buf; *cp == ' ' || *cp == '\t'; cp++);
+	    if (*cp == '\n' || *cp == '#') continue;
+	    if (!strcmp(buf2.string,cp)) return (1);
+	    if (*cp == '.' && strstr(buf2.string,cp)) return (1);
+	}
+	(void) fclose(fp);
+
+	return (0);
+#endif
+}
+
+news_socket()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qiow(0,s,IO$_SOCKET,&iosb,0,0,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qiow(0,s,IO$_SETMODE,&iosb,0,0,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+
+	return(1);
+}
+
+news_socket_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qio(*efn,s,IO$_SOCKET,biosb,astadr,*astprm,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) ) return(0);
+#else
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qio(0,s,IO$_SETMODE,biosb,astadr,*astprm,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) ) return(0);
+#else
+	return(-1);
+#endif
+#endif
+
+	return(1);
+}
+
+news_create()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qiow(0,s,IO$_CONNECT,&iosb,0,0,&sin,sizeof(sin),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+#if UCX 
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qiow(0,s,IO$_ACCESS,&iosb,0,0,0,0,&rhst_adrs,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+	if (!(sys$qiow(0,s,IO$_CREATE,&iosb,0,0,node,119,0,1,0,300) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#endif
+
+	return(1);
+}
+
+news_create_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qio(*efn,s,IO$_CONNECT,biosb,astadr
+		,*astprm,&sin,sizeof(sin),0,0,0,0) & 1)) return(0);
+#else
+#if UCX
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qio(*efn,s,IO$_ACCESS,biosb,astadr,*astprm,0,
+		0,&rhst_adrs,0,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_CREATE,biosb,astadr,*astprm,node,
+		119,0,1,0,300) & 1))
+	   return(0);
+#endif
+#endif
+
+	return(1);
+}
+
+news_connect()
+{
+	if (!news_gethost()) return(0);
+	if (!news_assign()) return(0);
+	if (!news_socket()) return(0);
+	return(news_create());
+}
+
+news_write_packet(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+#if CMU
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,!mode,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#else
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_write_packet_bullcp(efn,biosb,astadr,astprm,buf,len)
+int *biosb,*astadr,*astprm,*efn,*buf,*len;
+{
+#if CMU
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,!mode,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,0,0,0) & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_read_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+	if (!(sys$qiow(0,s,IO$_READVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+	n = iosb.size;
+
+	return(n);
+}
+
+news_gethostname(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	if (mode == DECNET) return (-1);
+#if TWG
+	return(gethostname(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+#if MULTINET
+	return(gethostname1(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+	return(-1);
+#endif
+#endif
+}
+
+
+smtp_assign()
+{
+	int n;
+
+#if MULTINET || TWG
+	/*
+	 *  Create a "sockaddr_in" structure which describes the remote
+	 *  IP address we want to send to (from gethostbyname()).
+	 */
+
+        if (!hp1) {
+          int h[4],i;
+          if (sscanf(node1,"%d.%d.%d.%d",&h[0],&h[1],&h[2],&h[3]) == 4) {
+            for (i=0;i<4;i++) if (h[i] < 0 || h[i] > 255) return(0);
+	    sin.sin_addr.s_addr = (h[3]<<24)+(h[2]<<16)+(h[1]<<8)+(h[0]);
+	  } else
+	    return(0);
+	  sin.sin_family = AF_INET;
+	}
+        else {
+ 	  sin.sin_family = hp1->h_addrtype;
+	  memcpy(&sin.sin_addr, hp1->h_addr, hp1->h_length);
+        }
+#if TWG
+	sin.sin_port = htons(25);
+#else
+	sin.sin_port = htons1(25);
+#endif
+
+	/*
+	 *  Create an IP-family socket on which to make the connection
+	 */
+
+	if (!(sys$assign(&inet_d,&s1,0,0) & 1)) return(0);
+#else
+#if UCX
+         if (!(sys$assign(&ucxdev_d,&s1,0,0) & 1)) return(0);
+	{
+           short retlen;
+	   struct dsc$descriptor host_name
+		= {strlen(node1),DSC$K_CLASS_S,DSC$K_DTYPE_T,node1};
+	   int comm = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYNAME;
+	   struct dsc$descriptor command
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&comm};
+	   struct dsc$descriptor host_ad
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&addr_buff};
+	   struct iosb nam_iosb;
+
+           if (!(sys$qiow(0,s1,IO$_ACPCONTROL,&nam_iosb,0,0,
+                       &command,&host_name,&retlen,&host_ad,0,0) & 1)
+               || !(nam_iosb.status & 1)) {
+              sys$dassgn(s);
+	      return(0);
+	   }
+	}
+#else
+	if (!(sys$assign(&ip_d,&s1,0,0) & 1)) return(0);
+#endif
+#endif
+	return(1);
+}
+
+
+smtp_create()
+{
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qiow(0,s1,IO$_CONNECT,&iosb,0,0,&sin,sizeof(sin),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#else
+#if UCX 
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(25);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qiow(0,s1,IO$_ACCESS,&iosb,0,0,0,0,&rhst_adrs,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+           sys$qiow(0,s1,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#else
+	if (!(sys$qiow(0,s1,IO$_CREATE,&iosb,0,0,node1,25,0,1,0,300) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#endif
+#endif
+
+	return(1);
+}
+
+smtp_disconnect()
+{
+#if UCX
+	sys$cancel(s1);
+	sys$qiow(0,s1,IO$_DEACCESS,0,0,0,0,0,0,0,0,0);
+#endif
+	sys$dassgn(s1);
+}
+
+
+smtp_connect()
+{
+	if (!smtp_gethost()) return(0);
+	if (!smtp_assign()) return(0);
+	if (!smtp_socket()) return(0);
+	return(smtp_create());
+}
+
+char node2[132];
+
+smtp_gethost()
+{
+	/*
+	 *  Get the IP address of the SMTP host.
+	 *  As of MULTINET 3.0, cannot be done at AST level
+	 *  so can't do in SMTP_ASSIGN(), as BULLCP calls it at
+	 *  AST level if the decnet gateway feature is used.
+	 */
+#if TWG
+	struct hostent *gethostbyname();
+#else
+#if MULTINET
+#endif
+#endif
+
+	node1 = getenv("BULL_SMTP_SERVER");
+	if (!node1) {
+#if TWG
+	   gethostname(node2,132);
+#else
+#if MULTINET
+	   gethostname1(node2,132);
+#endif
+#endif
+	   node1 = node2;
+	}
+
+#if TWG
+	hp1 = gethostbyname(node1);
+#else
+#if MULTINET
+	hp1 = gethostbyname1(node1);
+#endif
+#endif
+	return(1);
+}
+
+
+
+smtp_write_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+#if CMU
+	if (!(sys$qiow(0,s1,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,!mode,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#else
+	if (!(sys$qiow(0,s1,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+
+smtp_read_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+	if (!(sys$qiow(0,s1,IO$_READVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+	n = iosb.size;
+
+	return(n);
+}
+
+
+smtp_socket()
+{
+
+#if MULTINET || TWG
+	if (!(sys$qiow(0,s1,IO$_SOCKET,&iosb,0,0,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1)) {
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#endif
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qiow(0,s1,IO$_SETMODE,&iosb,0,0,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) || !(iosb.status & 1)) {
+           sys$qiow(0,s1,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#endif
+
+	return(1);
+}
diff --git a/decus/vmslt00a/bulletin/bull_newsdummy.for b/decus/vmslt00a/bulletin/bull_newsdummy.for
new file mode 100755
index 0000000000000000000000000000000000000000..90c0f814c6ad820f97eaee0e16df1203b8c0ea43
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bull_newsdummy.for
@@ -0,0 +1,137 @@
+	INTEGER FUNCTION NEWS_ASSIGN()
+
+	NEWS_ASSIGN = 0
+
+	RETURN
+	END
+
+	INTEGER FUNCTION NEWS_GET_CHAN(I)
+
+	NEWS_GET_CHAN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWS_SET_CHAN(I)
+
+	RETURN
+	END
+
+	INTEGER FUNCTION NEWS_SOCKET_BULLCP(I,J,K,L)
+
+	NEWS_SOCKET_BULLCP = 0
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION NEWS_CREATE_BULLCP(I,J,K,L)
+
+	NEWS_CREATE_BULLCP = 0
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION NEWS_WRITE_PACKET_BULLCP(I,J,K,L,M,N)
+
+	NEWS_WRITE_PACKET_BULLCP = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWS_DISCONNECT
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_CONNECT
+
+	NEWS_CONNECT = .FALSE.
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_WRITE_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_WRITE_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_READ_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_READ_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_GETHOSTNAME(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_GETHOSTNAME = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_GETHOST()
+
+	NEWS_GETHOST = 0
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SMTP_DISCONNECT
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION SMTP_CONNECT
+
+	SMTP_CONNECT = .FALSE.
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION SMTP_WRITE_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	SMTP_WRITE_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION SMTP_READ_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	SMTP_READ_PACKET = 0
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bullcom.cld b/decus/vmslt00a/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..7c2bf51ccc8b884c460e24f36e0a0dbd67510ab9
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullcom.cld
@@ -0,0 +1,771 @@
+!
+! BULLCOM.CLD
+!
+! VERSION 11/9/99
+!
+ 	MODULE BULLETIN_SUBCOMMANDS
+
+	DEFINE VERB ADD
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER BELL, NONNEGATABLE
+		QUALIFIER BROADCAST, NONNEGATABLE
+		DISALLOW NOT BROADCAST AND ALL
+		DISALLOW NOT BROADCAST AND BELL
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER CLUSTER, DEFAULT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT, NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		NONNEGATABLE
+		QUALIFIER LIST,DEFAULT
+		QUALIFIER LOCAL, NONNEGATABLE
+		DISALLOW LOCAL AND NOT BROADCAST
+		DISALLOW NODES AND SELECT_FOLDER
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		DISALLOW PERMANENT AND SHUTDOWN
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM, NONNEGATABLE
+	DEFINE VERB ATTACH
+		PARAMETER P1, LABEL=PROCESS, VALUE(TYPE=$FILE)
+		QUALIFIER PARENT
+		DISALLOW NOT PARENT AND NOT PROCESS
+		DISALLOW PARENT AND PROCESS
+	DEFINE VERB BACK
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB CHANGE
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER GENERAL, NONNEGATABLE
+		QUALIFIER HEADER, NONNEGATABLE
+		QUALIFIER NEW,NONNEGATABLE
+		QUALIFIER NUMBER, VALUE(TYPE=$FILE,REQUIRED)
+		QUALIFIER OWNER, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM,NONNEGATABLE
+		QUALIFIER TEXT, NONNEGATABLE
+		DISALLOW ALL AND NUMBER
+		DISALLOW NEW AND NOT EDIT
+		DISALLOW SYSTEM AND GENERAL
+		DISALLOW PERMANENT AND SHUTDOWN
+		DISALLOW PERMANENT AND EXPIRATION
+		DISALLOW SHUTDOWN AND EXPIRATION
+		DISALLOW SUBJECT AND HEADER
+	DEFINE VERB COPY
+		PARAMETER P1, LABEL=FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER ALL
+		QUALIFIER LOCAL
+		QUALIFIER MERGE
+		QUALIFIER ORIGINAL
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB CREATE
+		QUALIFIER ADD_ONLY, NONNEGATABLE
+		QUALIFIER ALWAYS, NONNEGATABLE
+		QUALIFIER BRIEF, NONNEGATABLE
+		QUALIFIER COMPRESS, NONNEGATABLE
+		QUALIFIER COPY, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER DESCRIPTION, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER ID, NONNEGATABLE
+!
+! Add ,DEFAULT to the end of the following line if you want CREATE to be
+! a privileged command.  NOTE: Make sure that BULL_DIR:BULLUSER.DAT
+! has the following protection:  (RWED,RWED,,)
+!
+		QUALIFIER NEEDPRIV, NONNEGATABLE
+		QUALIFIER NEWS
+		QUALIFIER NODE, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER NOTIFY, NONNEGATABLE
+		QUALIFIER OWNER, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER POST_ONLY, NONNEGATABLE
+		QUALIFIER PRIVATE, NONNEGATABLE
+		QUALIFIER READNEW, NONNEGATABLE
+		QUALIFIER REMOTENAME, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SEMIPRIVATE, NONNEGATABLE
+		QUALIFIER SHOWNEW, NONNEGATABLE
+		QUALIFIER SYSTEM, NONNEGATABLE
+		PARAMETER P1, LABEL=CREATE_FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		DISALLOW ID AND NOT OWNER
+		DISALLOW PRIVATE AND SEMIPRIVATE
+		DISALLOW BRIEF AND READNEW
+		DISALLOW SHOWNEW AND READNEW
+		DISALLOW BRIEF AND SHOWNEW
+		DISALLOW NODE AND (NOTIFY OR PRIVATE OR SEMIPRIVATE)
+		DISALLOW REMOTENAME AND NOT NODE
+		DISALLOW POST_ONLY AND ADD_ONLY
+	DEFINE VERB CURRENT
+		QUALIFIER EDIT
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB DELETE
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER IMMEDIATE,NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER FORCE
+		QUALIFIER LOCAL
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		QUALIFIER REASON, VALUE(REQUIRED)
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+		DISALLOW NOT SUBJECT AND (NODES OR SELECT_FOLDER)
+		DISALLOW NODES AND SELECT_FOLDER
+	DEFINE TYPE SEARCH_MATCHES
+	   	KEYWORD AND
+	   	KEYWORD OR
+	      		DEFAULT
+	   	KEYWORD XOR
+	DEFINE VERB DIRECTORY
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER ALL
+		QUALIFIER CONTINUE
+		QUALIFIER DELETE
+		QUALIFIER UNDELETE
+		QUALIFIER NEWS, SYNTAX=DIRECTORY_NEWS, NONNEGATABLE
+		QUALIFIER END, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER EXPIRATION
+		QUALIFIER EXTRACT, VALUE(TYPE=$FILE,REQUIRED)
+		QUALIFIER FEEDBACK
+		QUALIFIER FF
+		QUALIFIER FO, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+		QUALIFIER FOLDER, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+                QUALIFIER GROUP, VALUE(REQUIRED,LIST)
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER LOCAL
+		QUALIFIER NEW
+		QUALIFIER NOTIFY, DEFAULT
+		QUALIFIER PRINT
+		QUALIFIER QUEUE, VALUE(DEFAULT=SYS$PRINT), NONNEGATABLE
+                QUALIFIER FORM, VALUE, NONNEGATABLE
+		QUALIFIER MATCH, VALUE(DEFAULT="OR",TYPE=SEARCH_MATCHES)
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		QUALIFIER NOW
+		QUALIFIER OUTPUT,VALUE(REQUIRED,TYPE=$FILE)
+		QUALIFIER POST, DEFAULT
+		QUALIFIER REASON, VALUE(REQUIRED)
+		QUALIFIER START, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER ROTATE
+		QUALIFIER SEARCH, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SUBJECT, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER FROM, VALUE(REQUIRED), NONNEGATABLE
+                QUALIFIER NEGATED
+                DISALLOW GROUP AND
+			 NOT (SUBJECT OR SEARCH OR FROM OR NOREPLIES)
+                DISALLOW NEGATED AND 
+			 NOT (SUBJECT OR SEARCH OR FROM OR NOREPLIES)
+		DISALLOW (SUBJECT AND SEARCH) OR (SEARCH AND REPLY)
+		DISALLOW (FROM AND SUBJECT) OR (FROM AND NOREPLIES)
+		DISALLOW (NOREPLIES AND SUBJECT) OR (REPLY AND NOREPLIES)
+		DISALLOW (REPLY AND SUBJECT) OR (REPLY AND FROM)
+		DISALLOW (REPLY OR SUBJECT OR SEARCH OR FROM) AND
+			 (MARKED OR SEEN OR UNMARKED OR UNSEEN)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+		DISALLOW ALL AND (MARKED OR SEEN OR UNMARKED OR UNSEEN)
+		DISALLOW (NEW AND SINCE) OR (START AND NEW) OR (START AND SINCE)
+		DISALLOW DELETE AND UNDELETE
+	DEFINE SYNTAX DIRECTORY_NEWS
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER NEWS, DEFAULT, NONNEGATABLE
+		QUALIFIER DEFAULT
+		QUALIFIER PERMANENT
+		QUALIFIER SUBSCRIBE
+		QUALIFIER FOLDER
+		QUALIFIER NEWGROUPS
+		QUALIFIER ALL
+		QUALIFIER STORED
+		QUALIFIER CLASS
+		QUALIFIER COUNT
+	DEFINE SYNTAX DIRECTORY_FOLDER
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER DESCRIBE
+		QUALIFIER FOLDER, DEFAULT
+		QUALIFIER NEWS, NONNEGATABLE
+	DEFINE VERB E				! EXIT command.
+	DEFINE VERB EX				! EXIT command.
+	DEFINE VERB EXIT			! EXIT command.
+	DEFINE VERB EXCLUDE
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL
+		QUALIFIER LIMIT, VALUE
+		QUALIFIER SUBJECT
+		DISALLOW FULL AND (ALL OR P1 OR FROM OR SUBJECT)
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB EXTRACT
+		PARAMETER P1, LABEL=EXTRACT, VALUE(TYPE=$FILE)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER ALL
+		QUALIFIER FF
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW, NONNEGATABLE
+		QUALIFIER ROTATE
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB FILE
+		PARAMETER P1, LABEL=EXTRACT, VALUE(TYPE=$FILE)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER ALL
+		QUALIFIER FF
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW, NONNEGATABLE
+		QUALIFIER ROTATE
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB FIRST
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB FORWARD
+		PARAMETER P1, LABEL=RECIPIENTS, PROMPT="Recipients"
+		VALUE(REQUIRED,IMPCAT,LIST)
+		QUALIFIER EDIT, NONNEGATABLE
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB HELP
+		PARAMETER P1, LABEL=HELP_FOLDER, VALUE(TYPE=$REST_OF_LINE)
+	DEFINE VERB INCLUDE
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL 
+		QUALIFIER LIMIT, VALUE
+		QUALIFIER SUBJECT, DEFAULT
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB THREAD
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL 
+		QUALIFIER LIMIT, VALUE, NONNEGATABLE
+		QUALIFIER SUBJECT, DEFAULT
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB INDEX
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER EXPIRATION
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER FOLDER, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+		QUALIFIER NEW, DEFAULT
+		QUALIFIER MATCH, VALUE(DEFAULT="OR",TYPE=SEARCH_MATCHES)
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER RESTART
+		QUALIFIER SEARCH, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER SET , DEFAULT
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SUBSCRIBE
+		QUALIFIER PERMANENT
+		QUALIFIER NEGATED
+		QUALIFIER FROM, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SUBJECT, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER START, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		DISALLOW (NEW AND SINCE) OR (START AND NEW) OR (START AND SINCE)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB LAST
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB MAIL
+		PARAMETER P1, LABEL=RECIPIENTS, PROMPT="Recipients"
+		VALUE(REQUIRED,IMPCAT,LIST)
+		QUALIFIER EDIT, NONNEGATABLE
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB MARK
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB MODIFY
+		QUALIFIER DESCRIPTION
+		QUALIFIER ID, NONNEGATABLE
+		QUALIFIER NAME, VALUE(REQUIRED)
+		QUALIFIER OWNER, VALUE(REQUIRED)
+		DISALLOW ID AND NOT OWNER
+	DEFINE VERB MOVE
+		PARAMETER P1, LABEL=FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER FORCE
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LOCAL
+		QUALIFIER MERGE
+		QUALIFIER NODES
+		QUALIFIER ORIGINAL
+		QUALIFIER IMMEDIATE,NONNEGATABLE,DEFAULT
+		DISALLOW ALL AND BULLETIN_NUMBER
+		DISALLOW FOLDER AND NODES
+	DEFINE VERB NEWS
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER NEWS, DEFAULT, NONNEGATABLE
+		QUALIFIER COUNT
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SUBSCRIBE
+		QUALIFIER DEFAULT
+		QUALIFIER PERMANENT
+		QUALIFIER NEWGROUPS
+		QUALIFIER ALL
+		QUALIFIER STORED
+		QUALIFIER CLASS
+		DISALLOW CLASS AND (SUBSCRIBE OR START OR ALL OR STORED
+			 OR PERMANENT OR DEFAULT)
+		DISALLOW NEWGROUPS AND (SUBSCRIBE OR START OR ALL OR STORED
+					OR PERMANENT OR DEFAULT)
+		DISALLOW (DEFAULT AND PERMANENT) OR (DEFAULT AND SUBSCRIBE)
+		DISALLOW PERMANENT AND SUBSCRIBE
+	DEFINE VERB N
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+                QUALIFIER ROTATE
+	DEFINE VERB NEXT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+                QUALIFIER ROTATE
+	DEFINE VERB POST
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER EDIT
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST, DEFAULT
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER NOSIGNATURE
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB PRINT
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NOTIFY, DEFAULT
+		QUALIFIER QUEUE, VALUE(DEFAULT=SYS$PRINT), NONNEGATABLE
+                QUALIFIER FORM, VALUE, NONNEGATABLE
+		QUALIFIER NOW
+		QUALIFIER CANCEL
+		QUALIFIER ALL
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB QUIT
+	DEFINE VERB READ
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$NUMBER)
+		QUALIFIER ALL
+		QUALIFIER EDIT
+		QUALIFIER HEADER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER NEW
+		QUALIFIER PAGE, DEFAULT
+		QUALIFIER POST, DEFAULT
+		QUALIFIER ROTATE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER THREADS
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		DISALLOW NEW AND SINCE
+		DISALLOW BULLETIN_NUMBER AND (ALL OR NEW OR SINCE)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB REPLY
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER BELL, NONNEGATABLE
+		QUALIFIER BROADCAST, NONNEGATABLE
+		DISALLOW NOT BROADCAST AND ALL
+		DISALLOW NOT BROADCAST AND BELL
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER CLUSTER, DEFAULT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT, NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST,DEFAULT
+		QUALIFIER LOCAL
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		NONNEGATABLE
+		DISALLOW LOCAL AND NOT BROADCAST
+		DISALLOW NODES AND SELECT_FOLDER
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		DISALLOW PERMANENT AND SHUTDOWN
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM, NONNEGATABLE
+	DEFINE VERB REMOVE
+		PARAMETER P1, LABEL=REMOVE_FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+	DEFINE VERB RESET
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER CURRENT
+		DISALLOW CURRENT AND NUMBER
+	DEFINE VERB RESPOND
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		DISALLOW GROUPS AND NOT LIST
+		QUALIFIER EDIT
+	DEFINE VERB SEARCH
+		PARAMETER P1, LABEL=SEARCH_STRING, VALUE(LIST) 
+		QUALIFIER EDIT
+		QUALIFIER FEEDBACK
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER FROM
+                QUALIFIER GROUP, VALUE(REQUIRED,LIST)
+                QUALIFIER NEGATED
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER REVERSE
+		QUALIFIER START, VALUE(TYPE=$NUMBER)
+		QUALIFIER SUBJECT
+		QUALIFIER MATCH, VALUE(REQUIRED)
+		DISALLOW NOT (SEARCH_STRING OR REPLY) AND REVERSE
+		DISALLOW SEARCH_STRING AND REPLY
+		DISALLOW GROUP AND SELECT_FOLDER
+	DEFINE VERB SEEN
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER READ
+		DISALLOW (NUMBER AND (NEG READ OR READ))
+	DEFINE VERB SELECT
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB SET
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER ID
+	DEFINE TYPE SET_OPTIONS
+		KEYWORD NODE, SYNTAX=SET_NODE
+		KEYWORD NONODE, SYNTAX = SET_NONODE
+		KEYWORD EXPIRE_LIMIT, SYNTAX=SET_EXPIRE
+		KEYWORD NOEXPIRE_LIMIT
+		KEYWORD GENERIC, SYNTAX=SET_GENERIC
+		KEYWORD NOGENERIC, SYNTAX=SET_GENERIC
+		KEYWORD LIBRARY, SYNTAX=SET_LIBRARY
+		KEYWORD LOGIN, SYNTAX=SET_LOGIN
+		KEYWORD NOLOGIN, SYNTAX=SET_LOGIN
+		KEYWORD NOBBOARD
+		KEYWORD BBOARD, SYNTAX=SET_BBOARD
+		KEYWORD NOBRIEF, SYNTAX=SET_NOFLAGS
+		KEYWORD BRIEF, SYNTAX=SET_FLAGS
+		KEYWORD NOSHOWNEW, SYNTAX=SET_NOFLAGS
+		KEYWORD SHOWNEW, SYNTAX=SET_FLAGS
+		KEYWORD NOREADNEW, SYNTAX=SET_NOFLAGS
+		KEYWORD READNEW, SYNTAX=SET_FLAGS
+		KEYWORD ACCESS, SYNTAX=SET_ACCESS
+		KEYWORD NOACCESS, SYNTAX=SET_NOACCESS
+		KEYWORD FOLDER, SYNTAX=SET_FOLDER
+		KEYWORD NOTIFY, SYNTAX=SET_FLAGS
+		KEYWORD NONOTIFY, SYNTAX=SET_NOFLAGS
+		KEYWORD PRIVILEGES, SYNTAX=SET_PRIVILEGES
+		KEYWORD DUMP
+		KEYWORD NODUMP
+		KEYWORD PAGE
+		KEYWORD NOPAGE
+		KEYWORD SYSTEM
+		KEYWORD NOSYSTEM
+		KEYWORD KEYPAD
+		KEYWORD NOKEYPAD
+		KEYWORD PROMPT_EXPIRE
+		KEYWORD NOPROMPT_EXPIRE
+		KEYWORD DEFAULT_EXPIRE, SYNTAX=SET_DEFAULT_EXPIRE
+		KEYWORD STRIP
+		KEYWORD NOSTRIP
+		KEYWORD DIGEST
+		KEYWORD NODIGEST
+		KEYWORD CONTINUOUS_BRIEF
+		KEYWORD NOCONTINUOUS_BRIEF
+		KEYWORD ALWAYS
+		KEYWORD NOALWAYS
+		KEYWORD COMPRESS
+		KEYWORD NOCOMPRESS
+		KEYWORD POST_ONLY
+		KEYWORD NOPOST_ONLY
+		KEYWORD ADD_ONLY
+		KEYWORD NOADD_ONLY
+		KEYWORD NEWS, SYNTAX=SET_NEWS 
+		KEYWORD ANONYMOUS
+		KEYWORD NOANONYMOUS
+		KEYWORD EXLIMIT,SYNTAX=SET_EXLIMIT
+		KEYWORD EXCLUDE
+		KEYWORD NOEXCLUDE
+		KEYWORD NAME,SYNTAX=SET_NAME
+		KEYWORD SUBSCRIBE, SYNTAX=SET_SUBSCRIBE
+		KEYWORD FILE_DIRECTORY,SYNTAX=SET_FILE_DIRECTORY
+		KEYWORD GATEWAY
+		KEYWORD NOGATEWAY
+	DEFINE SYNTAX SET_EXLIMIT
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SET_PARAM2
+			VALUE(REQUIRED,TYPE=$NUMBER)
+	DEFINE SYNTAX SET_FILE_DIRECTORY
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SET_PARAM2
+	DEFINE SYNTAX SET_NAME
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=OLDNAME, VALUE(REQUIRED)
+		PARAMETER P3, LABEL=NEWNAME, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_NODE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=NODENAME, VALUE(REQUIRED)
+		PARAMETER P3, LABEL=REMOTENAME
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_NONODE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_EXPIRE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=EXPIRATION, VALUE(TYPE=$NUMBER,REQUIRED)
+	DEFINE SYNTAX SET_GENERIC
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME, VALUE(REQUIRED)
+		QUALIFIER DAYS,VALUE(TYPE=$NUMBER,DEFAULT="7"),DEFAULT
+	DEFINE SYNTAX SET_LOGIN
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_LIBRARY 
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=LIBRARY, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_FLAGS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+	DEFINE SYNTAX SET_NOFLAGS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+	DEFINE SYNTAX SET_SUBSCRIBE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+		DISALLOW NOT (ALL OR DEFAULT OR NODEFAULT OR PERMANENT
+			 OR NOPERMANENT)
+	DEFINE SYNTAX SET_BBOARD
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=BB_USERNAME
+		QUALIFIER EXPIRATION, VALUE(TYPE=$NUMBER)
+			LABEL=EXPIRATION, DEFAULT
+		QUALIFIER SPECIAL, NONNEGATABLE
+		QUALIFIER VMSMAIL, NONNEGATABLE
+		DISALLOW VMSMAIL AND NOT SPECIAL
+		DISALLOW VMSMAIL AND NOT BB_USERNAME
+	DEFINE SYNTAX SET_FOLDER
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SELECT_FOLDER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE SYNTAX SET_NOACCESS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=ACCESS_ID, VALUE(LIST)
+		PARAMETER P3, LABEL=ACCESS_FOLDER
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER CLASS, NONNEGATABLE
+		QUALIFIER READONLY, NONNEGATABLE
+		DISALLOW NOT ALL AND NOT ACCESS_ID
+		DISALLOW ALL AND NOT READONLY
+	DEFINE SYNTAX SET_NEWS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+		QUALIFIER ALL, DEFAULT
+		QUALIFIER CLASS,VALUE(REQUIRED)
+		QUALIFIER DEFAULT, NONNEGATABLE 
+		QUALIFIER DELETE, NONNEGATABLE 
+		QUALIFIER DISABLE, NONNEGATABLE
+		QUALIFIER ENABLE, NONNEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE(REQUIRED,
+				TYPE=$NUMBER)
+		QUALIFIER FULL
+		QUALIFIER LIMIT, NONNEGATABLE, VALUE(REQUIRED, 
+				TYPE=$NUMBER) 
+		QUALIFIER PRIVATE
+		QUALIFIER STORED
+  		DISALLOW (DEFAULT AND CLASS) OR (DELETE AND NOT CLASS)
+  		DISALLOW DEFAULT AND (DISABLE OR ENABLE OR PRIVATE)
+	DEFINE SYNTAX SET_ACCESS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=ACCESS_ID, VALUE(LIST)
+		PARAMETER P3, LABEL=ACCESS_FOLDER
+		QUALIFIER READONLY, NONNEGATABLE
+		QUALIFIER CLASS, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		DISALLOW NOT ALL AND NOT ACCESS_ID
+	DEFINE SYNTAX SET_PRIVILEGES
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=PRIVILEGES, PROMPT="Privileges"
+		VALUE (REQUIRED,LIST)
+	DEFINE SYNTAX SET_DEFAULT_EXPIRE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=DEFAULT_EXPIRE, VALUE(TYPE=$NUMBER,REQUIRED)
+	DEFINE VERB SHOW
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+!
+! The following are defined to allow qualifiers to be specified
+! directly after the SHOW command, i.e. SHOW/FULL FOLDER.
+! Otherwise, the CLI routines will reject the command, because it
+! first attempts to process the qualifier before process the parameter,
+! so it has no information the qualifiers are valid.
+!
+		QUALIFIER FULL, SYNTAX=SHOW_FOLDER_FULL, NONNEGATABLE
+		QUALIFIER ALL, SYNTAX=SHOW_USER
+		QUALIFIER FOLDER, VALUE, SYNTAX=SHOW_USER
+		QUALIFIER LOGIN, SYNTAX=SHOW_USER
+		QUALIFIER NOLOGIN, SYNTAX=SHOW_USER
+		QUALIFIER PRINT, SYNTAX=SHOW_KEYPAD_PRINT
+		QUALIFIER SINCE, VALUE(TYPE=$DATETIME), SYNTAX=SHOW_USER
+		QUALIFIER START, SYNTAX=SHOW_USER
+		QUALIFIER STATE, VALUE(LIST,DEFAULT=DEFAULT), NONNEGATABLE
+	DEFINE TYPE SHOW_OPTIONS
+		KEYWORD EXCLUDE
+		KEYWORD FLAGS, SYNTAX=SHOW_FLAGS
+		KEYWORD FOLDER, SYNTAX=SHOW_FOLDER
+		KEYWORD INCLUDE
+		KEYWORD KEYPAD, SYNTAX=SHOW_KEYPAD
+		KEYWORD LIBRARY, SYNTAX=SHOW_LIBRARY
+		KEYWORD NEW, SYNTAX=SHOW_FLAGS
+		KEYWORD PRIVILEGES, SYNTAX=SHOW_FLAGS
+		KEYWORD THREAD
+		KEYWORD USER, SYNTAX=SHOW_USER
+		KEYWORD VERSION
+	DEFINE SYNTAX SHOW_FLAGS
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+	DEFINE SYNTAX SHOW_KEYPAD
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+                PARAMETER P2, LABEL=SHOW_KEY
+		QUALIFIER PRINT
+		DISALLOW PRINT AND SHOW_KEY
+		QUALIFIER STATE, VALUE(LIST,DEFAULT=DEFAULT), NONNEGATABLE
+			DEFAULT
+	DEFINE SYNTAX SHOW_KEYPAD_PRINT
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		QUALIFIER PRINT,DEFAULT
+	DEFINE SYNTAX SHOW_LIBRARY
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		QUALIFIER ALL
+	DEFINE SYNTAX SHOW_FOLDER
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+	DEFINE SYNTAX SHOW_USER
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME
+		QUALIFIER ALL
+		QUALIFIER FOLDER, VALUE
+		QUALIFIER LOGIN
+		QUALIFIER NOLOGIN
+		QUALIFIER SINCE, VALUE(TYPE=$DATETIME)
+		QUALIFIER START, VALUE
+		DISALLOW (NOLOGIN OR LOGIN OR ALL) AND USERNAME
+		DISALLOW (LOGIN AND NOLOGIN)
+		DISALLOW (LOGIN OR NOLOGIN) AND FOLDER
+	DEFINE SYNTAX SHOW_FOLDER_FULL
+		QUALIFIER FULL, DEFAULT
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+	DEFINE VERB SUBSCRIBE
+        DEFINE VERB SPAWN
+		PARAMETER P1, LABEL=COMMAND, VALUE(TYPE=$REST_OF_LINE)
+	DEFINE VERB UNMARK
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB UNDELETE
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+	DEFINE VERB UNSEEN
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB UNSUBSCRIBE
diff --git a/decus/vmslt00a/bulletin/bullcoms1.hlp b/decus/vmslt00a/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..c82f17ae7b7088885bdbee2e717ddaf8bb187704
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullcoms1.hlp
@@ -0,0 +1,1276 @@
+1 ADD
+Adds a message to the specified folder.  A file can be  specified  which
+contains  the  message.    Otherwise, BULLETIN will prompt for the text.
+BULLETIN will ask for an expiration date and a  header  to  contain  the
+topic of the message. 
+
+  Format:
+    ADD [file-name]
+2 /ALL
+This option is restricted to privileged users.  It is used in conjunction
+with the /BROADCAST qualifier.  If specified, all terminals are sent the
+message.  Otherwise, only users are sent the message.
+2 /BELL
+This option is restricted to privileged users.  It is used in conjunction 
+with the /BROADCAST qualifier.  If specified, the bell is rung on the 
+terminals when the message is broadcasted.
+2 /BROADCAST
+This option is restricted to privileged users and SYSTEM  folders.    If
+specified,  a message is both stored and broadcasted to all users logged
+in at the time.  If the folder is remote, a message will be broadcast on
+all  nodes  which  are  connected  to  that  folder,  unless  /LOCAL  is
+specified.  A node which does not have  BULLCP  running  cannot  have  a
+message  broadcasted  to  it, (even though it is able to create a remote
+folder).   A broadcasted message is limited to 1600 characters
+
+See also /ALL and /BELL.
+2 /CLUSTER
+ /[NO]CLUSTER
+
+This option specifies that broadcasted messages should be sent to all
+nodes in the cluster.  /CLUSTER is the default.
+2 /EDIT
+ /[NO]EDIT
+Determines whether or not the editor is invoked to edit the message
+you are adding.  /EDIT is the default if you have added /EDIT to your
+BULLETIN command line.
+2 /EXPIRATION
+ /EXPIRATION=time
+
+Specifies the time at which the message is to expire.  Either absolute
+time: [dd-mmm-yyyy] hh:mm:ss, or delta time: dddd [hh:mm:ss] can be
+used.
+2 /EXTRACT
+Specifies that the text of the previously read message should be included
+at the beginning of the new message.  The previous message must be in the
+same folder.  This qualifier is valid only when used with /EDIT.  The
+text is indented with -> at the beginning of each line.  This can be
+suppressed or the indentation character changed with /[NO]INDENT.
+2 /FOLDER
+ /FOLDER=(foldername,[...])
+
+Specifies the foldername into which the message is to be  added.    Does
+not  change the current selected folder.  Folders can be either local or
+remote folders.  Thus, a  nodename  can  precede  the  foldername  (this
+assumes that the remote node is capable of supporting this feature, i.e.
+the BULLCP process is running on that node.  If  it  is  not,  you  will
+receive an error message).  If the the foldername is specified with only
+a nodename, i.e. FOO::, the foldername is  assumed  to  be  the  default
+folder.    NOTE: Specifying remote nodes is only possible if that remote
+node is running a special BULLCP process.  If it isn't, the only way  to
+add  messages  to  that  remote node is via the /NODE command.  /FOLDER,
+however, is a much quicker method, and much more versatile. 
+
+You can specify logical names which translate  to  one  or  more  folder
+names.   I.e.   $  DEFINE ALL_FOLDERS "VAX1,VAX2,VAX3", and then specify
+ALL_FOLDERS after /FOLDER=.  Note that the quotation marks are required.
+
+When using /FOLDER for remote nodes, proxy logins are used to  determine
+if privileged options are allowed.  If they are not allowed, the message
+will still be added, but without the privileged settings.
+2 /LOCAL
+Specifies  that  when  /BROADCAST  is specified for a remote folder, the
+message is broadcasted ONLY on the local node.
+2 /NODES
+ /NODES=(nodes[,...])
+
+Specifies  to send the message to the listed DECNET nodes.  The BULLETIN
+utility  must  be  installed  properly  on  the   other   nodes.    (See
+installation  notes). You can specify a different username to use at the
+other nodes by either using the USERNAME qualifier, or by specifying the
+nodename   with   2   semi-colons   followed   by   the  username,  i.e.
+nodename::username.  If you specify a username, you will be prompted for
+the password of the account on the other nodes.
+
+Additionally,  you  can  specify logical names which translate to one or
+more node names.  I.e.  $ DEFINE ALL_NODES  "VAX1,VAX2,VAX3",  and  then
+specify /NODES=ALL_NODES.  Note that the quotation marks are required.
+
+NOTE:  It  is  preferable  to  use /FOLDER instead of /NODE if possible,
+since adding messages via /FOLDER is much quicker.
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+2 /NOSIGNATURE
+Specifies to suppress the automatically appended signature, if one exists.
+Signatures are appended for postings to mailing lists and to responds.
+See the help topic POST Signature_file for signature information.
+2 /PERMANENT
+If specified, message will be a permanent message and will never expire.
+If an expiration limit is set, then permament is not allowed unless
+user has privileges.
+2 /SUBJECT
+ /SUBJECT=description
+
+Specifies the subject of the message to be added.
+2 /SHUTDOWN
+ /SHUTDOWN[=nodename]
+This option is restricted to privileged users.   If  specified,  message
+will  be  automatically  deleted after a computer shutdown has occurred.
+This option is restricted to SYSTEM folders. 
+
+If the bulletin files are shared between cluster nodes, the message will
+be  deleted  after  the  node on which the message was submitted from is
+rebooted.  If you wish the message to be deleted after a different  node
+reboots,  you have the option of specifying that node name.  The message
+deletion is keyed by BULLETIN running on the  node  that  reboots.    It
+writes  into  the  database  info  that  the node has rebooted, and when
+BULLCP wakes up and sees this info, it will delete any shutdown messages
+for that node. 
+
+NOTE: If the folder is a remote folder,  the  message  will  be  deleted
+after  the  remote node reboots, not the node from which the message was
+added.  The nodename cannot be specified with a remote folder. 
+2 /SYSTEM
+This option is restricted to privileged users.  If specified, message
+is both saved in the folder and displayed in full as a system message
+when a user logs in.  System messages should be as brief as possible to
+avoid the possibility that system messages could scroll off the screen.
+This option is restricted to SYSTEM folders.
+2 /USERNAME
+Specifies username to be used at remote DECNET nodes when adding messages
+to DECNET nodes via the /NODE qualifier.
+1 ATTACH
+Permits you to switch control of your terminal from your current process
+to another process in your job. 
+
+The ATTACH command allows you to move quickly between processes that you
+have created with the SPAWN command.  For example, while you are editing
+a file, you can SPAWN a subprocess to read a new  message.    Enter  the
+ATTACH  command to get back to back to the editing session.  If you want
+to read another new message, you can use the ATTACH command to get  back
+to the BULLETN subprocess you already created. 
+
+   Format:
+
+       ATTACH [/PARENT] [process-name]
+2 Parameters
+
+ process-name
+
+  Indicates the name of the subprocess to which the connection  is  to
+  be made. Only the /PARENT qualifier or a process-name may be specified.
+
+2 Qualifiers
+
+/PARENT
+
+   Allows you to attach to your process' parent process.
+   If there is no parent process an error message is printed.
+
+
+2 Examples
+
+  1.   
+       $ SPAWN BULLETIN
+       %DCL-S-SPAWNED, process MAGNANI_3 spawned
+       %DCL-S-ATTACHED, terminal now attached to process MAGNANI_3
+       BULLETIN> ATTACH MAGNANI_2
+       %DCL-S-RETURNED, control returned to process MAGNANI_2
+       $ ATTACH MAGNANI_3
+       BULLETIN>
+
+
+  This  example  shows  how  to  spawn  subprocesses  (MAGNANI_2   and
+  MAGNANI_3) to move from BULLETIN to DCL back to BULLETIN.  The ATTACH 
+  command  allows you to transfer control between subprocesses.
+
+
+                                  NOTE
+
+      You always SPAWN a new process and ATTACH to a process  that
+      already exists.
+1 BACK
+Displays the message preceding the current message.
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.
+If /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER for non-
+NEWS folders, /NOHEADER for NEWS folders.  If the SET STRIP command
+is set for the folder, it will change the default to be /HEADER.
+A user can make this option the default for a particular folder or
+news group.  See HELP Customizing.
+1 BULLETIN
+The BULLETIN utility permits a user to create a message for  reading  by
+all  users.    Users are notified upon logging in that new messages have
+been added, and what the topic of the messages are.  Actual  reading  of
+the  messages  is  optional.  (See  the  command SET READNEW for info on
+automatic  reading.)  Messages  are  automatically  deleted  when  their
+expiration date has passed. 
+1 CHANGE
+Replaces or modifies existing stored message.  This is for changing part
+or  all  of  a  message  without causing users who have already seen the
+message to be notified of it a second time.  You can  select  qualifiers
+so  that  either the message text, expiration date, or the header are to
+be changed.  If no qualifier is added, the default  is  that  all  these
+parameters  are  to  be  changed.    If the text of the message is to be
+changed, a file can be specified which contains the text.  If the editor
+is  used  for changing the text, the old message text will be extracted.
+This can be suppressed by the qualifier /NEW. 
+
+  Format:
+    CHANGE [file-name]
+2 /ALL
+Makes the changes to all the messages in the folder.  Only the expiration
+date and message headers can be changed if this qualifier is specified.
+2 /EDIT
+ /[NO]EDIT
+Determines whether or not the editor is invoked to edit the message
+you are replacing.  The old message text is read into the editor unless
+a file-name or /NEW is specified.  /EDIT is the default if you have
+added /EDIT to your BULLETIN command line.
+2 /EXPIRATION
+ /EXPIRATION[=time]
+
+Specifies the time at which the message is to expire.  Either absolute
+time: [dd-mmm-yyyy] hh:mm:ss, or delta time: dddd [hh:mm:ss] can be
+used.  If no time is specified, you will be prompted for the time.
+2 /GENERAL
+Specifies that the message is to be converted from a SYSTEM message to
+a GENERAL message.
+2 /HEADER
+Specifies that the message header is to be replaced.  You will be
+prompted for the new message description.
+2 /OWNER
+ /OWNER=string
+
+Specifies a new owner name.  Can only be changed if you own the folder
+or have privileges.
+2 /NEW
+If the editor is to be used for replacing the text of the message,
+NEW specifies not to read in the old message text, and that a totally
+new text is to be read in.
+2 /NUMBER
+ /NUMBER=message_number[-message_number1]
+
+Specifies the message or messages to be replaced. If this  qualifier  is
+omitted,  the  message that is presently being read will be replaced.  A
+range of  messages  can  be  specified,  i.e.  /NUMBER=1-5.    Only  the
+expiration  date  and  message  headers  can  be  changed  if a range is
+specified. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+2 /PERMANENT
+Specifies that the message is to be made permanent.
+2 /SHUTDOWN
+ /SHUTDOWN[=nodename]
+Specifies that the message is to expire after the next computer
+shutdown.  This option is restricted to SYSTEM folders.
+2 /SUBJECT
+ /SUBJECT=description
+
+Specifies the subject of the message to be added.
+2 /SYSTEM
+Specifies that the message is to be made a SYSTEM message.  This is a
+privileged command and is restricted to SYSTEM folders.
+2 /TEXT
+Specifies that the message text is to be replaced.
+1 COPY
+Copies a message to another folder  without  deleting  it  from  the
+current folder.
+
+  Format:
+
+    COPY folder-name [message_number][-message_number1]
+
+The folder-name is the name of the folder to which the message is to be
+copied to.  Optionally, a range of messages which are to be copied can be
+specified following the folder name, i.e. COPY NEWFOLDER 2-5.
+
+The key words CURRENT and LAST can also be specified in the range,
+in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.
+2 /ALL
+Specifies to copy all the messages in the old folder.
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected.  Specifies to send the message to
+the specified NEWS group(s) in addition to the selected NEWS group.
+2 /HEADER
+ /[NO]HEADER
+
+Valid only if destination folder is a news group.  Specifies that header
+of message is to be included with the text when the text is copied.
+The default is /NOHEADER.
+2 /LOCAL
+If specified and destination is a folder, the message will only be copied 
+to the folder, and will not be emailed to a corresponding email address or
+sent to a an associated news group, if either is present for the folder.
+If the destination is a news group, message header has line added to it
+to avoid having the message from being copied to a folder which has that
+news group feeding to it.
+2 /MERGE
+Specifies that the original date and time of the copied messages are
+saved and that the messages are placed in correct chronological order 
+in the new folder.  This operation is lengthy if the new folder is large.
+2 /ORIGINAL
+Specifies that the owner of the copied message will be the original owner
+of the message.  The default is that the copied message will be owned by
+the person copying the message.
+1 CREATE
+Creates a folder of messages.  This is similar to the folders in the VMS
+MAIL utility.  Folders are often created so that messages of  a  similar
+topic are grouped separately, or to restrict reading of certain messages
+to  specified  users.   Once  created,  that  message  is  automatically
+selected  (see information on SELECT command).  The commands that can be
+used to modify the folder's characteristics  are:  MODIFY,  REMOVE,  SET
+ACCESS, SET BBOARD, SET NODE, and SET SYSTEM.
+
+  Format:
+    CREATE folder-name
+
+The  folder-name is limited to 25 letters and must not include spaces or
+characters that are also invalid  in  filenames  (this  is  because  the
+folder is stored in a file name created with the folder name).
+
+NOTE:  Creation  of folders may be a restricted command if the installer
+has  elected  to  install  it  as  such.   This  is  done  by  modifying
+BULLCOM.CLD.
+2 /ALWAYS
+Specifies that  the  folder  has  the  ALWAYS  attribute.   This  causes
+messages  in  the  folder  to  be displayed differently when logging in.
+SYSTEM messages will be displayed every time a user logs in, rather than
+just  once.   Non-SYSTEM  message  will also be displayed every time (in
+whatever mode is selected, i.e. BRIEF, SHOWNEW, or  READNEW)  until  the
+user  actually  reads  that  message  (or a later one).  This feature is
+meant for messages which are very important, and thus you want  to  make
+sure they are read.
+2 /ADD_ONLY
+Specifies that the folder has the ADD_ONLY  attribute.    If  a  mailing
+address  is  present  (see /DESCRIPTION), when messages are added to the
+folder, they will also be mailed to the address.   Users  are  prevented
+from  using  the POST command.  Instead, the ADD command will be used if
+the POST command is entered.  One use for this is a local board which is
+also distributed to non-local users. 
+2 /BRIEF
+Specifies that all users automatically have BRIEF set for  this  folder.
+Only  a privileged user can use this qualifier.  (See HELP SET BRIEF for
+more information.)
+2 /DESCRIPTION
+ /DESCRIPTION=description
+
+Specifies the description of the folder, which is  displayed  using  the
+SHOW FOLDER command.  If omitted, you are prompted for a description. 
+
+If this folder is to receive messages from a network  mailing  list  via
+the  BBOARD  feature,  and  you  wish  to  use the POST and RESPOND/LIST
+commands, the address of the mailing list  should  be  included  in  the
+description.  This is done by enclosing the address using <> and placing
+it at the end of the description, i.e. 
+
+              INFOVAX MAILING LIST <INFO-VAX@KL.SRI.COM>
+
+You can also use this feature to have messages  which  are  added  to  a
+folder  to  be  mailed to the email address.  This is common if you have
+users that don't have access to BULLETIN.  Note:  When  you  specify  an
+email address, the folder automatically will have the ADD_ONLY flag set,
+which causes both ADD and POST to both add a message and send  mail  the
+message.  Note that a message added to the folder via the BBOARD feature
+will also be mailed to the specified email address.  In this way,  users
+without  access  to  BULLETIN  can  add  messages by sending mail to the
+BBOARD account.  If you create a remote  folder  pointing  to  a  folder
+associated  with an email address, you must specify the email address in
+the description of the remote folder also.  Please also read  about  the
+SET GATEWAY command. 
+
+It is also possible to use the description to specify a news group from
+which messages are fed into the folder.  See the file FOLDER_TO_NEWS.TXT
+for more info.
+2 /ID
+Designates that the name  specified  as  the  owner  name  is  a  rights
+identifier.    The  creator's process must have the identifier presently
+assigned to it.  Any process which has that identifier  assigned  to  it
+will  be  able  to  control the folder as if it were the folder's owner.
+This is used to allow more than one  use  to  control  a  folder.    The
+identifier can not be any longer than 12 characters. 
+
+Note: This feature will not work during remote access to the folder.
+2 /NODE
+ /NODE=node
+
+Specifies that the folder is a remote folder at the specified node.    A
+remote folder is a folder in which the messages are actually stored on a
+folder at a remote DECNET node.  The specified node is checked to see if
+a  folder  of  the same name is located on that node.  If so, the folder
+will then be modified to point to that folder.  For example if there was
+a folder on node A with name INFO, and you issued the command: 
+                        CREATE INFO/NODE=A
+from node B, then if INFO is selected  on  node  B,  you  will  actually
+obtain  the  folder  INFO  on  node  A.  In this manner, a folder can be
+shared between more than one node. This capability is  only  present  if
+the  BULLCP  process  is running on the remote node via the BULL/STARTUP
+command.  If the remote folder name is different from the  local  folder
+name,  the  remote  folder  name  is  specified  using  the  /REMOTENAME
+qualifier. 
+
+NOTE: If a message is added to a remote  node,  the  message  is  stored
+immediately.    However,  a  user logging into another node might not be
+immediately alerted that the message is present.   That  information  is
+only  updated  every  15  minutes  (same  algorithm  for updating BBOARD
+messages), or if a user accesses that folder.  Thus, if  the  folder  is
+located on node A, and the message is added from node B, and a user logs
+in to node C, the BULLETIN login notification might not notify the  user
+of  the  message.  However, if the message is added with /BROADCAST, the
+message will be broadcasted immediately to all nodes. 
+2 /NOTIFY
+Specifies that all users automatically have NOTIFY set for this  folder.
+Only a privileged user can use this qualifier.  (See HELP SET NOTIFY for
+more information.)
+2 /OWNER
+ /OWNER=username
+Specifies the owner of the folder.  This is a privileged command.
+See also /ID.
+2 /POST_ONLY
+Specifies that the folder has the POST_ONLY attribute.  This causes 
+the ADD command to mail the message to the mailing address if it is 
+present (see /DESCRIPTION), rather than add to the folder.  
+2 /PRIVATE
+Specifies that the folder can only be accessed by users  who  have  been
+granted  access via the SET ACCESS command.  Note: This option uses ACLs
+and users who are granted access must be entered into  the  Rights  Data
+Base.   If the RDB does not exist on your system, a privileged user will
+have to create it.  If a user is not  in  the  RDB,  this  program  will
+automatically  enter  the user into it (unless this feature was disabled
+during the compilation of this program).  NOTE: See HELP SET ACCESS  for
+more info. 
+
+WARNING:  This command can not be used with remote nodes.    Create  the
+folder  without  it and then use SET ACCESS to change protection.  Also,
+access protection on the remote node will override local protection. 
+2 /READNEW
+Specifies that all users automatically have READNEW set for this folder.
+Only  a  privileged  user can use this qualifier.  (See HELP SET READNEW
+for more information.)
+2 /REMOTENAME
+ /REMOTENAME=foldername
+Valid only if /NODE is present, i.e. that the folder is a remote folder.
+Specifies the name of the remote folder name.  If not specified, it is
+assumed that the remote name is the same as the local name.
+2 /SHOWNEW
+Specifies that all users automatically have SHOWNEW set for this folder.
+Only a privileged user can use this qualifier.  (See HELP SET SHOWNEW for
+more information.)
+2 /SEMIPRIVATE
+Similar to /PRIVATE, except that the folder is restricted only with
+respect to adding or modifying messages.  All users can read the folder.
+
+WARNING:  This command can not be used with remote nodes.  Create the 
+folder without it and then use SET ACCESS to change protection.  Also,
+access protection on the remote node will override local protection.
+2 /SYSTEM
+Specifies that the folder is a SYSTEM folder.  A SYSTEM folder is
+allowed to have SYSTEM and SHUTDOWN messages added to it.  This is a
+privileged command.
+                                                         
+If this is a remote folder, /SYSTEM cannot be specified unless the
+folder at the other node is also a SYSTEM folder.
+1 Ctrl-C
+Except for when BULLETIN is awaiting input from the terminal, a 
+CTRL-C will cause BULLETIN to abort the execution of any command.  If
+BULLETIN is waiting for terminal input, a CTRL-C will cause BULLETIN
+to return to the BULLETIN> prompt.  If for some reason the user wishes
+to suspend BULLETIN, CTRL-Y will usually do so.  However, this is not
+always true, as BULLETIN will ignore the CTRL-Y if it has a data file
+opened at the time. (Otherwise it would be possible to put the files
+in a state such that they would be inaccessible by other users.)
+1 CURRENT
+Displays the beginning of the message you are currently reading.  If
+you  are  reading  a long message and want to display the first part
+of the message again, you can enter the CURRENT command.
+
+  Format:
+
+    CURRENT
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.  If
+either /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER  for  non-
+NEWS  folders,  /NOHEADER for NEWS folders.  If the SET STRIP command is
+set for the folder, it will change the default to be /HEADER.    A  user
+can  make this option the default for a particular folder or news group.
+See HELP Customizing. 
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
+1 DELETE
+Deletes the specified message.  If no message is specified, the  current
+message  is  deleted.   Only the original owner or a privileged user can
+delete a message.  Note that the message is not deleted immediately, but
+its expiration is set 15 minutes in the future.  This is to allow a user
+to recover the message using the UNDELETE command.    If  you  want  the
+message deleted immediately, use the /IMMEDIATE qualifier. 
+
+  Format:
+    DELETE [message_number][-message_number1]
+
+The message's relative number is found by the DIRECTORY command.  It  is
+possible  to  delete  a  range  of  messages  by  specifying two numbers
+separated by a dash, i.e. DELETE  1-5.    However,  a  range  cannot  be
+specified if the folder is remote. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+2 /ALL
+Specifies to delete all the messages in the folder.  Note:  This will
+not work for remote folders.  Only one message can be deleted from a
+remote folder at a time.
+2 /IMMEDIATE
+Specifies that the message is to be deleted immediately.  Not applicable
+to news groups that are stored on disk.
+2 /LOCAL
+Only used with news groups stored on disk.  Only the local message will
+be deleted.  No delete message will be sent to the Usenet network to
+delete the message at other nodes.
+2 /NODES
+ /NODES=(nodes[,...])
+
+Specifies to delete the  message  at  the  listed  DECNET  nodes.    The
+BULLETIN utility must be installed properly on the other nodes.  You can
+specify a different username to use at the other nodes by  either  using
+the USERNAME qualifier, or by specifying the nodename with 2 semi-colons
+followed by the username, i.e. nodename::username.   If  you  specify  a
+username,  you  will  be prompted for the password of the account on the
+other nodes.  The /SUBJECT must be specified to  identify  the  specific
+message that is to be deleted. 
+
+Additionally, you can specify logical names which translate  to  one  or
+more  node  names.   I.e.  $ DEFINE ALL_NODES "VAX1,VAX2,VAX3", and then
+specify /NODES=ALL_NODES.  Note that the quotation marks are required. 
+2 /SUBJECT
+ /SUBJECT=subject
+
+Specifies the subject of the bulletin to be deleted at a  remote  DECNET
+node.   The DECNET node must be specified with the /NODE qualifier.  The
+specified subject need not be the exact subject of the message.  It  can
+be  a  substring of the subject.  This is in case you have forgotten the
+exact subject that was specified.  Case is not  critical  either.    You
+will be notified if the deletion was successful.  See also /NEGATED. 
+2 /USERNAME
+Specifies username to be used  at  remote  DECNET  nodes  when  deleting
+messages on other DECNET nodes via the /NODE qualifier. 
+1 DIRECTORY
+Lists a summary of the messages.  The message number, submitter's  name,
+date, and subject of each message is displayed. 
+
+  Format:
+
+    DIRECTORY [folder]
+
+If  a  folder is specified, that folder is selected before the directory
+is listed.  Unless otherwise specified, listing starts  with  the  first
+newest message.  If there are no new messages, listing will start at the
+first message, or if a message has already been read, it will  start  at
+that message.
+2 /ALL
+Lists all messages.  Used if the qualifiers /MARKED, /UNMARKED, /SEEN,
+or /UNSEEN were previously specified. 
+2 /CONTINUE
+Used with /GROUP.  Allows you to continue a search after you have broken
+the  search by entering a command, i.e. READ, SEARCH, etc.  Note: If you
+enter a SEARCH command which specifies a string, and then  continue  the
+directory  search using /CONTINUE, the new search pattern will be used
+when continuing the search. 
+2 /DELETE
+Deletes all the messages which are displayed.  Immediate deletes are not
+available in this mode.  Paging is turned off while deleting occurs.
+2 /UNDELETE
+Undeletes all the messages which are displayed.
+2 /DESCRIBE 
+Valid when used with /FOLDERS.  Specifies to include description of
+folder.
+2 /EXPIRATION
+Shows the message's expiration date rather than the creation date.
+2 /END
+ /END=message_number
+
+Indicates the last message number you want to display.
+2 /EXTRACT
+ /EXTRACT=filename
+
+Specifies that the text of the messages which are found by the DIRECTORY
+command are to be written into the specified file.  All qualifiers which
+are valid for the EXTRACT command are valid in conjunction with /EXTRACT
+except  for /NEW which conflicts with the DIRECTORY /NEW qualifier.  The
+listof messages to be printed will be  displayed  on  the  terminal  (in
+nopaging format). 
+
+See the command SET FILE_DIRECTORY for info  on  setting  the  directory
+where files are stored.   The default directory is SYS$LOGIN.
+2 /FEEDBACK
+Used only in conjunction with /GROUP.  Specifies to show when  new  news
+groups are selected. 
+2 /FOLDERS
+Lists the available message folders.  Shows last message date and number
+of  messages  in  folder.   An asterisk (*) next to foldername indicates
+that there are unread messages in  that  folder.   This  will  not  show
+newsgroups.  To see newsgroups, use the NEWS command or DIR/NEWS.
+2 /FROM
+ /FROM=[string]
+
+Specifies that only messages whose username contains the specified string
+are to be displayed.  This cannot be used in conjunction with /MARKED.  
+If no string is specified, the previously specified string is used.
+See also /NEGATED.
+2 /GROUP
+   /GROUP=(string,[...])
+
+Specifies a list of groups  to  be  searched.    Used  with  the  search
+qualifiers  /SEARCH, /SUBJECT, or /FROM.  Wildcards are permitted in the
+specified string.  Use /FEEDBACK to see when groups are  selected.    At
+any  time  during the search you may enter other commands, i.e.  you may
+read a message, see a full directory listing, etc.  You may then restart
+the  search  listing by typing DIR/CONTINUE.  For more info, see help on
+the /CONTINUOUS qualifier. 
+2 /NEGATED
+Used with /SUBJECT, /FROM, & /SEARCH.  If specified, messages who don't
+match the specified search command are displayed.
+2 /MARKED
+Lists messages that have been marked (indicated by an asterisk).
+This is equivalent to selecting the folder with /MARKED, i.e. only
+marked messages will be shown and be able to be read.  To see all
+messages, use either /ALL, or reselect the folder. 
+2 /UNMARKED
+Lists messages that have not been marked (marked messages are indicated
+by an asterisk).  Using /UNMARKED is equivalent to selecting the folder
+with /UNMARKED, i.e. only unmarked messages will be shown and be able
+to be read.  To see all messages, use either /ALL, or reselect the
+folder. 
+2 /SEEN
+Lists messages that have been seen (indicated by a greater than sign). 
+Using /SEEN is equivalent to selecting the folder with /SEEN, i.e. only
+seen messages will be shown and be able to be read.  To see all
+messages, use either /ALL, or reselect the folder. 
+2 /UNSEEN
+Lists messages that have not been seen (seen message are indicated by a
+greater than sign). Using /UNSEEN is equivalent to selecting the folder
+with /UNSEEN, i.e. only unseen messages will be shown and be able to be
+read.  To see all messages, use either /ALL, or reselect the folder. 
+2 /NEW
+Specifies  to  start  the  listing  of  messages  with  the first unread
+message.
+2 /NEWS
+Lists the available news groups.  This does the same thing as  the  NEWS
+command.  See that command for qualifiers which apply.
+2 /OUTPUT
+ /OUTPUT=filename
+
+Specifies to write the directory output to a file rather than the
+terminal.
+2 /PRINT
+Specifies that the text of the messages which are found by the
+DIRECTORY command are to be printed.  All qualifiers which are valid
+for the PRINT command are valid in conjunction with /PRINT.  The list
+of messages to be printed will be displayed on the terminal (in
+nopaging format). 
+2 /REPLY
+Specifies that only messages which are replies to the current message
+are to be displayed.  This cannot be used in conjunction with /MARKED.
+2 /NOREPLIES
+Specifies that only messages which are not replies (i.e. whose subject
+do not start with RE:) are to be displayed.  This cannot be used in 
+conjunction with /MARKED.
+2 /SEARCH
+ /SEARCH=[string]
+
+Specifies that only messages which contain the specified string are
+to be displayed.  This cannot be used in conjunction with /MARKED.
+If no string is specified, the previously specified string is used.
+See also /NEGATED.
+2 /SINCE
+ /SINCE=date
+
+Displays a listing of all the messages created on or after the
+specified date.  If no date is specified, the default is TODAY.
+2 /START
+ /START=message_number
+
+Indicates the first message number you want to display.  For example,
+to  display  all the messages beginning with number three, enter the
+command line DIRECTORY/START=3.  Not valid with /FOLDER.
+2 /SUBJECT
+ /SUBJECT=[string]
+
+Specifies that only messages which contain the specified string in  it's
+subject  header are to be displayed.  This cannot be used in conjunction
+with /MARKED.  If no  string  is  specified,  the  previously  specified
+string is used. 
+1 EXCLUDE
+Specifies to exclude reading messages based on the message owner or  the
+subject.  If it is determined that a message is to be excluded, then the
+message is skipped when a user tries to read a message bytyping NEXT  or
+BACK,  or by hitting the return key.  Specify /FULL to make all EXCLUDEs
+and INCLUDEs for the  specified  folder  apply  to  all  other  BULLETIN
+commands, including directory listings.
+
+  Format:
+    EXCLUDE [string]
+
+If a string is specified, then the message is excluded if the  owner  or
+the subject contains that string, depending on whether /FROM or /SUBJECT
+is specified.  Otherwise, if no string is specified, then the owner name
+or subject of the current message is used.  /FROM is the default.
+
+Note:  EXCLUDEs based on FROM will take precedence over INCLUDEs.
+2 /ALL
+Used with /DISABLE to specify to disable all EXCLUDEs.
+2 /DISABLE
+Specifies to permanently disable the EXCLUDE.
+2 /FROM
+Specifies to exclude the message based on the message owner.  This is
+the default.  /FROM and /SUBJECT cannot be specified at the same time.
+2 /FULL
+If specified, causes all excludes and includes for the  selected  folder
+to  be  applied  to all BULLETIN commands, including directory listings.
+See help customizing for info on how to make this the  default  for  all
+folders.    Note  that  specifying  this  may  substantially  slow  down
+directory listings.  When /FULL is specified, the EXCLUDE  command  will
+not add an exclude,  so it can't be used with any other qualifier except
+for /DISABLE.
+2 /LIMIT
+   /LIMIT=days
+
+Specifies that the exclude will be automatically deleted if no match  is
+found  for the specified number of days.  The default is no limit, which
+is specified by 0.  This can be changed via the SET EXLIMIT command. 
+2 /SUBJECT
+Specifies to exclude the message based on the message subject.  /FROM
+and /SUBJECT cannot be specified at the same time. 
+2 Storing_EXCLUDEs
+EXCLUDEs are stored in the file SYS$LOGIN:BULL.CUSTOM or in the file
+pointed to by the logical name BULL_USER_CUSTOM.  The format is:
+
+folder_name:EXCLUDE:FROM(or SUBJECT):string
+
+In order for /FULL to be the default for a folder, the following line
+must be present:
+
+folder_name:defaults:kill
+
+excluding the folder_name causes it to apply to all folders.
+1 EXIT
+Exits the BULLETIN program.
+1 EXTRACT
+Synonym for FILE command.
+1 FILE
+Copies the current message to the named file.  If the file  exists,  the
+message is appended to the file, unless the /NEW qualifier is specified. 
+
+  Format:
+    FILE [filename] [message_number][-message_number1],[...]
+
+If the filename is omitted, a file will be created based on the name  of
+the folder. 
+
+A range of messages to be copied can optionally be specified, i.e.  FILE
+2-5.  The key words CURRENT and LAST can also be specified in the range,
+in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+
+See the command SET FILE_DIRECTORY for info  on  setting  the  directory
+where files are stored.   The default directory is SYS$LOGIN.
+2 /ALL
+Copies all the messages in the current folder.
+2 /FF
+Specifies that a form feed is placed between messages in the file.
+2 /HEADER
+ /[NO]HEADER
+
+Controls whether a header containing the owner, subject, and date of the 
+message is written in the file.  The default is to write the header.
+2 /NEW
+
+Specifies that a new file is to be created.  Otherwise, if the specified
+file exists, the file would be appended to that file.
+1 FIRST
+Specifies that the first message in the folder is to be read.
+1 Folders
+All messages are divided into separate folders.    New  folders  can  be
+created  by any user.  As an example, the following creates a folder for
+GAMES related messages: 
+                                               
+BULLETIN> CREATE GAMES
+Enter a one line description of folder.
+GAMES
+
+To see the list of available folders, use DIRECTORY/FOLDERS.  To  select
+a specific folder, use the SELECT command. 
+
+If a user selects a folder and enters the SET READNEW command, that user
+will  be  alerted of topics of new messages at login time, and will then
+be given the option of reading them.  Similar  to  READNEW  is  SHOWNEW,
+which displays the topics but doesn't prompt to read them.  Even less is
+SET BRIEF, which will cause only a one line output indicating that there
+are  new  messages  in the folder.  There also is the SET NOTIFY option,
+which will cause a message to be broadcast to a user's terminal alerting
+the user that a new message has been added.  Any of these options can be
+the default for the folder by using the /DEFAULT switch on the command. 
+
+A folder can be restricted to only certain users, if desired.   This  is
+done  by specifying CREATE/PRIVATE.  Afterwards, access to the folder is
+controlled by the creator by the SET [NO]ACCESS command.  If instead you
+specify /SEMIPRIVATE, all users can read the messages in the folder, but
+only those given access can add messages. 
+
+A folder can be converted into a remote folder using CREATE/NODE or  SET
+NODE.    A  remote  folder  is  one which points to a folder on a remote
+DECNET node.  Messages added to a remote node are actually stored on the
+folder   on   the   remote   node.    The  BULLCP  process  (created  by
+BULLETIN/STARTUP) must be running on the remote node for this option  to
+be used. 
+
+A folder can be specified as a SYSTEM folder, i.e. one in which  SYSTEM/
+SHUTDOWN/BROADCAST messages can be added.  One use for this is to create
+a remote SYSTEM folder which is shared by all nodes, so that the default
+folder is used for messages pertaining only to the local host, while the
+remote folder is used for messages pertaining to all nodes.  Another use
+is  to  create  a  folder  for  posting SYSTEM messages only meant for a
+certain UIC group.  This is done by creating a  PRIVATE  SYSTEM  folder,
+and  giving access to that UIC group.  Only users in that UIC group will
+see the messages in that folder when they log in. 
+1 FORWARD
+Synonym for MAIL command.
+1 HELP
+To obtain help on any topic, type:
+
+        HELP  topic
+1 INCLUDE
+This command is a synonym for the THREAD command.
+1 INDEX
+Gives directory listing of all folders or subscribed groups in
+alphabetical order.  Useful for scanning your folders or news groups for 
+new messages without having to manually select them.  If the INDEX
+command is re-entered while the INDEX scan is in progress, the scan will
+skip to the next folder.  This is useful for skipping past a folder.  It
+also can be used to continue the scan from where one left off after one
+has read a message.  /RESTART must be specified to start from the first
+folder if a scan is in progress.  All other qualifiers are ignored while 
+a scan is in progress.
+
+  Format:
+       INDEX
+
+When a directory is displayed, you can read the first message in the 
+list by typing READ.
+
+NOTE:  /NEW and /SET are the defaults.  This was not the case for older
+versions of BULLETIN.
+2 /MARKED
+Lists messages that have been marked (marked messages are indicated by
+an asterisk).  This is equivalent to selecting the folder with /MARKED,
+i.e. only marked messages will be shown and be able to be read. 
+2 /UNMARKED
+Lists messages that have not been marked (marked messages are indicated
+by an asterisk).  Using /UNMARKED is equivalent to selecting the folder
+with /UNMARKED, i.e. only unmarked messages will be shown and be able
+to be read.
+2 /SEEN
+Lists messages that have been seen (indicated by a greater than sign). 
+Using /SEEN is equivalent to selecting the folder with /SEEN, i.e. only
+seen messages will be shown and be able to be read.
+2 /UNSEEN
+Lists messages that have not been seen (seen message are indicated by a
+greater than sign). Using /UNSEEN is equivalent to selecting the folder
+with /UNSEEN, i.e. only unseen messages will be shown and be able to be
+read.
+2 /NEW
+ /[NO]NEW
+
+Specifies to list only those folders or groups that have new unread
+messages, and to start the listing with the first unread message.
+Otherwise, the listing will start with the first message.  /NEW is the
+default.  Is ignored if /[UN]SEEN or /[UN]MARKED are specified.
+2 /RESTART
+If specified, causes the listing to be reinitialized and start from the
+first folder.
+2 /SET
+ /[NO]SET
+
+Specifies that only folders that have READNEW, BRIEF, or SHOWNEW set are
+to be shown.  SET is the default.  Ignored if /SUBSCRIBE is specified.
+2 /SUBSCRIBE
+If specified, lists only news groups which have been subscribed to. 
+1 KEYPAD
+             +--------+--------+--------+--------+
+             | PF1    | PF2    | PF3    | PF4    |
+             |   GOLD |   HELP | EXTRACT|SHOW KEY|
+             |        |ST NOKEY|  FILE  |SH KY/PR|
+             |--------|--------|--------|--------|
+             | 7      | 8      | 9      | --     |
+             |  ADD   | REPLY  |  MAIL  |READ/NEW|
+             | ADD/EDI|RP/ED/EX|M/NOHEAD|SHOW NEW|
+             |--------|--------|--------|--------|
+             | 4      | 5      | 6      | ,      |
+             | CURRENT| RESPOND|  LAST  | DIR/NEW|
+             |CURR/EDI|RS/ED/EX|        |  INDEX |
+             |--------|--------|--------|--------|
+             | 1      | 2      | 3      |ENTER   |
+             |  BACK  |  PRINT |   DIR  |        |
+             |  NEXT  |P/NONOTI|DIR/FOLD|        |
+             |--------+--------|--------| ENTER  |
+             | 0               | .      | SELECT |
+             | SHOW FOLDER/FULL| DELETE |        |
+             |    SHOW FLAGS   | UNDELE |        |
+             +-----------------+--------+--------+
+2 Suggestions
+Here are keypads settings that the author personally uses.    Note  that
+the IND/SUBS commands are useful only for reading NEWS. 
+
+DEFINE/KEY PERIOD "IND/SUBS"/TERM
+DEFINE/KEY PERIOD "IND/SUBS/NONEW"/IF_STATE=GOLD/TERM  
+DEFINE/KEY MINUS "READ/THREAD"/IF_STATE=GOLD/TERM
+DEFINE/KEY PF1 ""/IF_STATE=GOLD/SET=NOEDIT
+DEFINE/KEY PF1 ""/IF_STATE=NOEDIT/SET=NOH
+DEFINE/KEY PF3 "EXT"/TERM
+DEFINE/KEY KP9 "MAIL/EDIT/NOHEAD"/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP8 "REPLY/NOEDIT"/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP7 "SEND/NOEDIT"/IF_STATE=NOEDIT/TERM 
+DEFINE/KEY KP4 "CUR/H"/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP4 "CUR/NOH"/IF_STATE=NOH/TERM
+DEFINE/KEY KP5 "RESPOND/NOEDIT "/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP5 "RESPOND/EXTRACT/LIST/EDIT "/TERM
+DEFINE/KEY KP2 "SEARCH/REP "/TERM
+DEFINE/KEY KP2 "SEARCH/REV/REP "/TERM/IF_STATE=GOLD
+DEFINE/KEY KP2 "SEARCH/REV "/IF_STATE=NOEDIT
+DEFINE/KEY COMMA "SPAWN"/TERM
+1 LAST
+
+Displays the last message in the current folder.
+
+  Format:
+       LAST
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.
+If /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER for non-
+NEWS folders, /NOHEADER for NEWS folders.  If the SET STRIP command
+is set for the folder, it will change the default to be /HEADER.
+A user can make this option the default for a particular folder or
+news group.  See HELP Customizing.
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
+1 MAIL
+Invokes the VAX/VMS Personal Mail Utility (MAIL) to send the message
+which you are reading to the specified recipients.
+
+  Format:
+
+    MAIL recipient-name[s]
+
+The input for the recipient name is exactly the same format as used by
+the MAIL command at DCL level.  Note that this means when specifying an
+address that has quotes, in order to pass the quotes you must specify
+triple quotes.  I.e. a network address of the form xxx%"address" must
+be specified as xxx%"""address""".
+2 /EDIT
+Specifies that the editor is to be used to edit the message before
+mailing it.
+2 /HEADER
+ /[NO]HEADER
+
+Controls whether a header containing the owner, subject, and date of the 
+message is written in the mail.  The default is to write the header.
+2 /SUBJECT
+ /SUBJECT=text
+
+Specifies the subject of the mail message. If the text consists of more
+than one word, enclose the text in quotation marks (").
+
+If you omit this qualifier, the description of the message will be used
+as the subject.
+1 MARK
+Sets the current or message-id message as marked. Marked messages are
+displayed with an asterisk in the left hand column of the directory
+listing.  A marked message can serve as a reminder of important
+information.  The UNMARK command sets the current or message-id message
+as unmarked.
+
+   Format:
+
+       MARK [message-number or numbers]
+       UNMARK [message-number or numbers]
+
+NOTE: The list of marked messages for non-NEWS folders are stored in a
+file username.BULLMARK, and NEWS folders are stored in
+username.NEWSMARK. The files are created in the directory pointed to by
+the logical name BULL_MARK.  If BULL_MARK is not defined, SYS$LOGIN
+will be used. 
+1 MODIFY
+Modifies the database information for the current folder.  Only the
+owner of the folder or a user with privileges can use this command. 
+
+  Format:
+
+    MODIFY
+2 /DESCRIPTION
+Specifies a new description for the folder.  You will be prompted for
+the text of the description.
+
+NOTE: If this folder is to receive messages from a network mailing  list
+via  the  BBOARD  feature, and you wish to use the POST and RESPOND/LIST
+commands, the address of the mailing list  should  be  included  in  the
+description.  This is done by enclosing the address using <> and placing
+it at the end of the description, i.e. 
+
+              INFOVAX MAILING LIST <INFO-VAX@KL.SRI.COM>
+
+You can also use this feature to have messages  which  are  added  to  a
+folder  to automatically mailed to the email address.  This is common if
+you have users that don't have access to BULLETIN.  In order to do this,
+you should use the SET ADD_ONLY command.  This causes all messages added
+to the folder to also be sent to the email address.  This  also  applies
+to  messages which are added via the BBOARD feature.  In this way, users
+without access to BULLETIN can add  messages  by  sending  mail  to  the
+BBOARD account.  Please also read about the SET GATEWAY command.
+2 /ID
+Designates that the name specified as the owner name is a rights
+identifier.  The creator's process must have the identifier presently
+assigned to it.  Any process which has that identifier assigned to it
+will be able to control the folder as if it were the folder's owner.
+This is used to allow more than one use to control a folder.
+
+Note: This feature will not work during remote access to the folder.
+2 /NAME
+ /NAME=foldername
+
+Specifies a new name for the folder.
+2 /OWNER
+ /OWNER=username
+
+Specifies a new owner for the folder.  If the owner does not have
+privileges, BULLETIN will prompt for the password of the new owner
+account in order to okay the modification.  See also /ID.
+1 MOVE
+Moves a message to another  folder  and  deletes  it  from  the  current
+folder. 
+
+  Format:
+
+    MOVE folder-name [message_number][-message_number1]
+
+The folder-name is the name of the folder to which the message is to  be
+be  moved to.  Optionally, a range of messages which are to be moved can
+be specified  following  the  folder  name,  i.e.  COPY  NEWFOLDER  2-5.
+However,  if  the  old  folder  is  remote,  they will be copied but not
+deleted, as only one message can be delted from a  remote  folder  at  a
+time. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+2 /ALL
+Specifies to move all the messages from the old folder.  Note:  If the
+old folder is remote, they will be copied but not deleted, as only one
+message can be deleted from a remote folder at a time.
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected.  Specifies to send the message to
+the specified NEWS group(s) in addition to the selected NEWS group.
+2 /HEADER
+ /[NO]HEADER
+
+Valid only if destination folder is a news group.  Specifies that header
+of message is to be included with the text when the text is copied.
+The default is /NOHEADER.
+2 /LOCAL
+If specified and destination is a folder, the message will only be moved
+to the folder, and will not be emailed to a corresponding email address or
+sent to a an associated news group, if either is present for the folder.
+If the destination is a news group, message header has line added to it
+to avoid having the message from being copied to a folder which has that
+news group feeding to it.
+2 /MERGE
+Specifies that the original date and time of the moved messages are
+saved and that the messages are placed in correct chronological order 
+in the new folder.  This operation is lengthy if the new folder is large.
+2 /ORIGINAL
+Specifies that the owner of the moved message will be the original owner
+of the message.  The default is that the moved message will be owned by
+the person moving the message.
+1 NEWS
+Displays the list of available news groups.
+
+Format:
+
+	NEWS [string]
+
+If  the  string is specified, lists news groups whose name contains that
+string.  If the string contains an asterisk, a wild card match  will  be
+applied.   I.e.  if ALT* is specified, all groups starting with ALT will
+be displayed.
+
+The status column of the display shows the status  of  the  news  group.
+"y"  means  the  news  group  is available.  "m" means the news group is
+moderated, and posting may or may not  be  allowable.    "="  means  the
+newsgroup  has  been renamed.  The new name is shown on the display line
+immediately following the old name. 
+
+Only those news groups which are enabled are shown.   Adding  /ALL  will
+show both enabled and disabled groups.  If this is done, the status will
+show "x" if the group has been deactived by the news  server  feed,  and
+"n" if the group has been deactived locally. 
+2 /ALL
+If specified, all news groups will be shown, including those that have
+been disabled.
+2 /CLASS
+If specified, will show news group classes.  For more info on classes,
+see help for SET NEWS/CLASS.
+2 /COUNT
+If specified, will show number of messages in the news group instead
+of the status.
+2 /DEFAULT
+If specified, will show news groups that have be defined as default 
+groups using the SET SUBSCRIBE command.
+2 /NEWGROUP
+If specified, will list new news groups that have been added since the
+last time that a user has accessed a news group.  If there are new
+groups, a user will see a message indicating that there are new groups
+when the user accesses a news group.
+2 /PERMANENT
+If specified, will show news groups that have be defined as permanent
+groups using the SET SUBSCRIBE command.
+2 /START
+ /START=string
+
+If specified, the list will start with the  first  group  which  follows
+alphabetically  after  that  string.  I.e. if /START=B is specified, the
+list will start with groups whose name starts with a B.
+2 /STORED
+If specified, only those news groups which are stored on disk are shown.
+2 /SUBSCRIBE
+If specified, lists only those news folders which have been subscribed to.
+An asterisk before the group indicates that new messages are present for
+that folder.
+1 New_features
+Here is a list of new features which may be of interest to the general 
+BULLETIN user.  If you find a bug or have a good suggestion for a new 
+feature, send mail to MRL@PFC.MIT.EDU.
+
+-------------------------------------------------------------------------
+V 2.24
+Removed INCLUDE command and replaced it with the THREAD command.    This
+allows  you  to  save  and  easily  read new messages in threads via the
+READ/THREADS command.  11/13/95
+
+V 2.23
+Added /LIMIT to EXCLUDE and also the SET EXLIMIT command.   These  allow
+excludes to be specified so that they expire after a specified amount of
+days.  The SHOW EXCLUDE now will show the last time a message was found 
+that matched the exclude.  8/16/95
+
+Added /GROUP qualifier to DIRECTORY command to allow  specifying  groups
+to search using wild cards names.  8/3/95
+
+Added /GROUP qualifier to SEARCH command to allow specifying  groups  to
+search using wild cards names.  6/20/95
+
+V 2.22
+
+SHOW EXCLUDE and INCLUDE commands added.  5/16/95
+
+V 2.21
+
+Added /CANCEL to PRINT command which cancels previous print commands.
+10/28/94
+
+Added /FOLLOWUP to POST command when used with news groups.  It specifies
+which news group you want replies to your message to be sent to.  10/28/94
+
+V 2.20
+
+Logical names can be specified in POST/GROUPS=.  5/12/94
+
+Added SET FILE_DIRECTORY command.  5/11/94
+
+V 2.19
+
+Add /MATCH qualifier to SEARCH command, and allow more than 1 string to be
+specified.  12/2/93
+
+V 2.18
+
+Added SET [NO]EXCLUDE command to be  able  to  ignore  any  excludes  or
+includes that have been specified for that folder.  5/20/93
+
+V 2.17
+
+Added /FULL to EXCLUDE  and  INCLUDE  command  to  make  it  affect  all
+commands, such as directory listings.  5/13/93
+
+V 2.15
+
+A user can make /HEADER be made the default for a folder or news group by
+adding a line to the user's customization file.  2/21/93
+
+Added /EXTRACT qualifie to DIRECTORY command.  1/31/93
+
+V 2.13
+
+Added /[NO]HEADER and /ROTATE to NEXT (help said they were there, but they
+weren't).  1/15/93
+
+Added RESET command.  1/9/93
+
+V 2.12
+
+Added INCLUDE and EXCLUDE commands which allow avoiding reading messages
+based on subject and address headers.  12/15/92
+
+V 2.11
+
+NEWS command now by default shows only groups which are active. Can show all
+groups with /ALL command. /STORED and /COUNT are new qualifiers. 11/5/92
+
+INDEX command modified to make it more useful. /NEW is now the default,  and
+now  only shows folders or groups that have new messages. /SET added to show
+only folders which have READNEW, SHOWNEW, or BRIEF  set,  and  /SET  is  the
+default. 11/5/92
+
+Folder names can now be up to 44 letters long.  11/5/92
+
+Added /ROTATE for read commands to allow reading messages encoded in  ROT-13
+coding.  This is used by some news groups to display messages which could be
+taken as being offensive (i.e. rec.humor.funny). 11/5/92
+1 NEXT
+Skips to the next message and displays it.  This is useful when paging
+through the messages and you encounter a particularly long message
+that you would like to skip over.
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.
+If /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER for non-
+NEWS folders, /NOHEADER for NEWS folders.  If the SET STRIP command
+is set for the folder, it will change the default to be /HEADER.
+A user can make this option the default for a particular folder or
+news group.  See HELP Customizing.
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
+1 Personal_name
+Any messages posted to news groups or sent as  mail  automatically  will
+include  the personal name which is set in the VMS mail utility.  If you
+don't  want  this  to  happen,  you  can   define   the   logical   name
+BULL_PERSONAL_NAME to be the personal name you want BULLETIN to use: 
+
+$ DEFINE BULL_PERSONAL_NAME "John Doe"
+$ BULLETIN
+
+If you don't want any personal name, define it to be " ".
diff --git a/decus/vmslt00a/bulletin/bullcoms2.hlp b/decus/vmslt00a/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..89713750f9d2e6764412babad4aa464b7cedf5c3
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullcoms2.hlp
@@ -0,0 +1,1463 @@
+1 POST
+If a NEWS group is selected, posts a message to that group.  If a normal
+folder is selected, sends a message via MAIL to the network mailing list
+which  is  associated  with  the  selected  folder.   The address of the
+mailing  list  must  be  stored  using  either   CREATE/DESCRIPTION   or
+MODIFY/DESCRIPTION.  See help on those commands for more information.
+
+  Format:
+    POST [file-name]
+2 /CC
+ /CC=user[s]
+Specifies additional users that should receive the mail message.
+2 /EDIT
+Specifies that the editor is to be used for creating the mail message.
+2 /EXTRACT
+Specifies that the text of the message that  is  being  read  should  be
+included  in  the  mail message.  This qualifier is valid only when used
+with /EDIT.  The text  of  the  message  is  indented  with  ->  at  the
+beginning  of  each  line.    This  can be suppressed or the indentation
+character changed with /[NO]INDENT.
+2 /FOLLOWUP
+ /FOLLOWUP=string
+
+Specifies that any replies  generated  by  people  reading  the  message
+should  be  sent to the specified newsgroup.  This is useful if you want
+to post to more than one group, but don't want reply messages posted  on
+all  the  groups.  To specify more than one newsgroup, surround the list
+with quotes, i.e.  FOLLOWUP="newsgroup1,newsgroup2".  If replies  should
+only  be  sent  to  the  message  owner  and not a newsgroup, the string
+"poster" should be specified. 
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected.  Specifies to send  the  message
+to  the  specified NEWS group(s) in addition to the selected NEWS group.
+Logical names are allowed. 
+2 /HEADER
+Allows customized headers line to be added to the message header.   When
+specified, header lines can be added by inserting them at the top of the
+message, with the header lines and the text of the message separated  by
+a blank line. 
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+2 /NOSIGNATURE
+Specifies to suppress  the  automatically  appended  signature,  if  one
+exists.    Signatures  are appended for postings to mailing lists and to
+responds.    See  the  help  topic  POST  Signature_file  for  signature
+information. 
+2 /SUBJECT
+ /SUBJECT=text
+
+Specifies the subject of the mail message. If the text consists of  more
+than one word, enclose the text in quotation marks ("). 
+
+If you omit this qualifier, you will prompted for the subject.
+2 Signature_file
+It is possibly to have the contents of a file be automatically  appended
+to  the end of a message added with the POST and/or the RESPOND command.
+This file is known as a signature file, and it typically contains  one's
+name, address, or perhaps a favorite quote.  The name of the file should
+be SYS$LOGIN:BULL_SIGNATURE.TXT, and it should be a  simple  text  file.
+In  order  to  specify  a different file to use, define the logical name
+BULL_SIGNATURE to point to the desired file. 
+
+It is possible to specify that portions or all of the signature file are
+to  be  included  only  for  specific  folders  or  news groups.  Simply
+surround the exclusive text starting with the line "START <folder-name>"
+and ending with the line "END", i.e. 
+
+START INFOVAX
+This line will only appear in the INFOVAX folder.
+END
+START MISC.TEST
+This line will only appear in the news folder MISC.TEST.
+END
+This line will appear in all postings.
+
+Note that an empty line is automatically created to separate the text of
+the message and the contents of the signature file.
+1 PRINT
+Queues a copy of the message you are currently  reading  (or  have  just
+read)  for  printing.    The  file  created  by the PRINT command is not
+released to the print queue until you exit, unless you add the qualifier
+/NOW or change one of the print job's qualifiers.  Multiple messages are
+concatenated into one print job. 
+
+   Format:
+
+       PRINT [message_number][-message_number1],[...]
+
+A range of messages to be printed  can  optionally  be  specified,  i.e.
+PRINT 2-5. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+
+NOTE:  The qualifier /PRINT is present on the DIRECTORY command.    This
+provides  more  flexibility than is present with the PRINT command.  For
+example, if you want to print all messages with a particular  string  in
+it's subject line, DIRECTORY/PRINT/SUBJ would allow you do it. 
+2 /ALL
+Prints all the messages in the current folder.
+2 /CANCEL
+Cancels any messages waiting to be printed.
+2 /FORM
+Specifies the name or number of the form that you  want  for  the  print
+job.    Codes  for form types are installation-defined.  You can use the
+SHOW QUEUE/FORM command  at  DCL  level  to  find  out  the  form  types
+available for your system.  Use the SHOW QUEUE/FULL command at DCL level
+to find out the name of the mounted form and  the  default  form  for  a
+particular  queue.   If you specify a form whose stock is different from
+the stock of the form mounted on the queue, your  job  is  placed  in  a
+pending  state  until  the stock of the mounted form of the queue is set
+equal to the stock of the form associated with the job.   (In  order  to
+have  your  job  print,  the  system  manager  should  stop  the  queue,
+physically change the paper stock on the output device, and restart  the
+queue specifying the new form type as the mounted form.)
+2 /HEADER
+ /[NO]HEADER
+
+Controls whether a header containing the owner, subject, and date of the 
+message is printed at the beginning. The default is to write the header.
+2 /NOTIFY
+ /[NO]NOTIFY
+
+Indicates that you will be notified by a broadcast message when the file
+or  files  have  been  printed.   If /NONOTIFY is specified, there is no
+notification.  The default is /NOTIFY. 
+2 /NOW
+Sends all messages that have been queued for  printing  with  the  PRINT
+command during this session to the printer. 
+2 /QUEUE
+ /QUEUE=queue_name
+
+The name of the queue to which a message is to be sent.  If  the  /QUEUE
+qualifier  is not specified, the message is queued to SYS$PRINT.
+1 QUIT
+Exits the BULLETIN program.
+1 READ
+Displays the specified message.  If you do not specify a  message,  then
+the  first  time  you enter the command, the first message in the folder
+will be displayed.  However, if there are new messages,  the  first  new
+message  will  be  displayed.  Each time you enter the command, the next
+page, or if there are no more pages, the next message will be displayed. 
+
+  Format:
+    READ [message-number]
+
+The message's relative number is found by the DIRECTORY command.  If you
+specify  a number greater than the number of messages in the folder, the
+last message in the folder will be displayed. 
+
+NOTE: The READ command can be abbreviated by omitting the READ  command,
+i.e.  typing  the  command  "2"  is  equivalent  to "READ 2", and simply
+hitting the <RETURN> key is equivalent to "READ". 
+
+BULLETIN normally stores only the latest message that has been read  per
+folder.  It  can  optionally  store and display which messages have been
+read in a folder on a per message basis.  For information on  this,  see
+the help on the SEEN command.
+2 /ALL
+Specifies to read all messages.  Used after /MARKED, /UNMARKED, /SEEN,
+or /UNSEEN had been specified.
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.  If
+/HEADER  or  /NOHEADER  is  specified,  the  setting  will apply for all
+further reads in the selected folder.  The default is /HEADER  for  non-
+NEWS  folders,  /NOHEADER for NEWS folders.  If the SET STRIP command is
+set for the folder, it will change the default to be /HEADER.    A  user
+can  make this option the default for a particular folder or news group.
+See HELP Customizing. 
+2 /MARKED
+Specifies to read only messages that have been marked (marked messages
+are indicated by an asterisk).  Using /MARKED is equivalent to
+selecting the folder with /MARKED, i.e. only marked messages will be
+shown and be able to be read.   To see all messages, use either /ALL,
+or reselect the folder. 
+2 /UNMARKED
+Specifies to read only messages that have not been marked (marked
+messages are indicated by an asterisk).  Using /UNMARKED is equivalent
+to selecting the folder with /UNMARKED, i.e. only unmarked messages
+will be shown and be able to be read.  To see all messages, either
+reselect the folder or specify /ALL.
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
+2 /SEEN
+Specifies to read only messages that have been seen (indicated by a
+greater than sign). Using /SEEN is equivalent to selecting the folder
+with /SEEN, i.e. only seen messages will be shown and be able to be
+read.  To see all messages, use either /ALL, or reselect the folder. 
+2 /UNSEEN
+Specifies to read only messages that have not been seen (seen message
+are indicated by a greater than sign). Using /UNSEEN is equivalent to
+selecting the folder with /UNSEEN, i.e. only unseen messages will be
+shown and be able to be read.  To see all messages, use either /ALL, or
+reselect the folder. 
+2 /THREADS
+Reads all messages that have been included by the THREAD  command.    If
+neither  message  number nor /SINCE is specified, the search starts with
+the first new message.  After the  first  READ/THREADS  command,  typing
+READ/THREADS will continue the search from where it left off (as long as
+you do not select a different folder or news  group).    Also,  after  a
+message has been fully read, if the return key is hit without entering a
+command, it is equivalent to typing the READ/THREADS command.   Messages
+which  are  parts  of  threads  and  under read will be displayed in the
+directory listing by a preceeding #. 
+2 /NEW
+Specifies to read the first unread message.
+2 /PAGE
+ /[NO]PAGE
+
+Specifies that the display of the message will pause when it reaches the
+end of the page.  If /NOPAGE is specified, the whole message will be
+displayed.  This is useful for terminals that can store more than one
+screenful at a time, and that have a remote printer that can then print
+the contents of the terminal's memory.
+2 /SINCE
+ /SINCE=date
+
+Specifies to read the first message created on or after the specified
+date.  If no date is specified, the default is TODAY.
+1 REMOVE
+Removes a folder.  Only the owner of a folder or a privileged  user  can
+remove the folder.
+
+  Format:
+    REMOVE folder-name
+1 REPLY
+Adds message with subject of message being the subject of the  currently
+read message with "RE:" preceeding it.  Format and qualifiers is exactly
+the same as the ADD command except for /INDENT and /EXTRACT.
+
+  Format:
+    REPLY [file-name]
+2 /EXTRACT
+Specifies that the text of the message should be included in the reply
+mail message.  This qualifier is valid only when used with /EDIT.  The
+text of the message is indented with -> at the beginning of each line.
+This can be suppressed or the indentation character changed using 
+the qualifer /[NO]INDENT.
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+1 RESET
+Resets the new message counter for the selected folder  or  news  group.
+The  new  message counter stores the latest read message, and is used to
+determine if there are new messages to be read. 
+
+  Format:
+    RESET [message-number]
+
+If no number is specified, the last message in used.    This  is  useful
+when  you  want to simply ignore any new messages without having to read
+them.  (Note: Reading the last message does the same  thing,  but  RESET
+does it without having to read it.)
+2 /CURRENT
+Resets the new message counter to the current message.
+1 RESPOND
+Invokes the VAX/VMS Personal Mail Utility (MAIL) to send a reply mail
+message to the owner of the currently read message.
+
+  Format:
+    RESPOND [file-name]
+
+If you wish to use another method for sending the mail, define BULL_MAILER
+to point to a command procedure.  This procedure will then be executed in
+place of MAIL, and the parameters passed to it are the username and subject
+of the message.
+2 /CC
+ /CC=user[s]
+Specifies additional users that should receive the reply.
+2 /EDIT
+Specifies that the editor is to be used for creating the reply mail
+message.
+2 /EXTRACT
+Specifies that the text of the message should be included in  the  reply
+mail  message.   This qualifier is valid only when used with /EDIT.  The
+text of the message is indented with -> at the beginning of  each  line.
+This  can  be  suppressed or the indentation character changed using the
+qualifer /[NO]INDENT. 
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected or /LIST is present.    Specifies
+to  send  the  message to the specified NEWS group(s) in addition to the
+selected NEWS group. 
+2 /LIST
+Specifies that the reply should also be sent to the network mailing list
+associated  with  the folder.  The mailing list address should be stored
+in the folder description.  See CREATE/DESCRIPTION or MODIFY/DESCRIPTION
+for more informaton. 
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+2 /NOSIGNATURE
+Specifies to suppress  the  automatically  appended  signature,  if  one
+exists.    Signatures  are appended for postings to mailing lists and to
+responds.    See  the  help  topic  POST  Signature_file  for  signature
+information. 
+2 /SUBJECT
+ /SUBJECT=text
+
+Specifies the subject of the mail message. If the text consists of  more
+than one word, enclose the text in quotation marks ("). 
+
+If you omit this qualifier, the description of the message will be  used
+as the subject preceeded by "RE: ". 
+1 SEARCH
+Searches the currently selected folder for the  message  containing  the
+first occurrence of the specified text strings.
+
+   Format:
+
+       SEARCH [search-string[,...]]
+
+The search starts from the first message in the current folder.  You can
+specify  the message to start at using the qualifier /START.  If you use
+this qualifier without a parameter, it starts with the current  message.
+The  search  includes  both the text of the message, and the description
+header.  If a "search-string" is not specified, a search is  made  using
+the previously specified string, starting with the message following the
+one you are currently reading (or have just read).  After fully  reading
+the  message  found  by  the  search,  if you hit the return key without
+entering a command, it is equivlanent to typing SEARCH without a  search
+string and will search for the next message.  Once started, a search can
+be aborted by typing a CTRL-C. 
+2 /EDIT
+Specifies that the editor is to be used for reading the message.
+2 /FEEDBACK
+Used only in conjunction with /FOLDER and /GROUP.    Specifies  to  show
+when new folders or news groups are selected. 
+2 /FOLDER
+   /FOLDER=(folder,[...])
+
+Specifies a list of folders to be searched.  The search  will  start  by
+selecting  the first folder in the list and searching the messages for a
+match.  If, during a search, no more matches or messages are found,  the
+next  folder  in  the  list  is  automatically  selected.  The presently
+selected folder can be included in the search by specifying  ""  as  the
+first  folder  in  the  list.    Use  /FEEDBACK  to see when folders are
+selected.  News groups can be specified here.  However, to search news
+group with wild cards, use /GROUP.
+2 /GROUP
+   /GROUP=(string,[...])
+
+Specifies a list of groups to be searched.  Wildcards are  permitted  in
+the specified string.  	If the string does not contain an * and does not
+specify a news group, * is automatically placed at the beginning and end
+of  the  string.    I.e.  if  the string is "comp", then all news groups
+containing the word "comp" will be searched.  Use /FEEDBACK to see  when
+groups are selected.
+2 /FROM
+Specifies that only the username of the messages are to be searched.
+2 /MATCH
+ /MATCH[=option]
+
+Interprets and matches multiple search strings in one of  the  following
+ways: 
+
+     AND      A match occurs only if all of the strings are found.
+
+     OR       A match occurs if any of the strings are found.
+
+     XOR      A match occurs if only one of the strings is found.
+
+If you specify none of these options, the default is /MATCH=OR.  If  you
+specify the /NEGATED qualifier, you will get the negated operation. 
+2 /NEGATED
+If specified, messages that don't match the specified search string
+command are displayed.  Does not work with /NOREPLIES.
+2 /NOREPLIES
+Specifies to find messages which are not replies (i.e. whose subject
+do not start with RE:).
+2 /REPLY
+Specifies that messages are to be searched for that are replies  to  the
+currently read message, or the message specified by /START.  Replies are
+messages which have subject of the original message prefaced by "Re:". 
+2 /REVERSE
+Specifies that the messages are to be searched in reverse order.  If  no
+starting  message  is  specified,  the  search  is started from the last
+message.  /REVERSE must be specified with a search string.
+2 /START
+ /START=message_number
+
+Specifies the message number to start the search at.  If  you  omit  the
+message number, it starts with the current message. 
+2 /SUBJECT
+Specifies that only the subject of the messages are to be searched.
+1 SEEN
+Sets the current or message-id message as seen. This allows you to keep
+track of messages on a per message basis.  Seen messages are displayed
+with a greater than sign in the left hand column of the directory
+listing.  Once you have used the SEEN command once, messages will be
+automatically be set as being SEEN when they are read.  The UNSEEN
+command sets the current or message-id message as unseen. 
+
+   Format:
+
+       SEEN [message-number or numbers]
+       UNSEEN [message-number or numbers]
+
+Keeping track of seen messages requires very little overhead for NEWS
+folders.  However, there is a moderate overhead for regular non-NEWS
+folders.  If you have used the SEEN command and wish to disable the
+automatic marking of messages in regular folders as SEEN when they are
+read, type the command SEEN/NOREAD.  To reenable, simply use the SEEN
+command again. 
+
+If a specified message is newer than the newest read message, then the
+newest read message counter will be updated.  The newest read message 
+counter is used to determine if there are new messages to be read.
+You are alerted of this when entering BULLETIN or selecting a folder
+or news group.  If you simply want to reset this counter and don't care
+about marking which messages have been seen or not, use the RESET command.
+
+NOTE: The list of SEEN messages for non-NEWS folders are stored in a
+file username.BULLMARK, and NEWS folders are stored in
+username.NEWSMARK. The files are created in the directory pointed to by
+the logical name BULL_MARK.  If BULL_MARK is not defined, SYS$LOGIN
+will be used. 
+1 SELECT
+Selects a folder of messages.  See HELP Folders for a description  of  a
+folder.   Once a folder has been selected, all commands, i.e. DIRECTORY,
+READ, etc. will apply only to those messages.  Use the CREATE command to
+create  a  folder.   Use the DIRECTORY/FOLDER command to see the list of
+folders that have been created.
+
+ Format:
+
+     SELECT [node-name::][folder-name]
+
+The complete folder name need not be specified.  BULLETIN  will  try  to
+find the closest matching name.  I.e. INFOV can be used for INFOVAX.
+
+Omitting the folder name will select the default folder.
+
+The  node  name can be specified only if the remote node has the special
+BULLCP process running (invoked by BULLETIN/STARTUP command.)
+
+After selecting a folder, the user will notified of the number of unread
+messages,  and  the  message  pointer will be placed at the first unread
+message.
+
+BULLETIN automatically determines if the selcted name is a NEWS group by
+detecting if a period is present in the name being  specified,  as  most
+NEWS  groups  contain  a  period,  whereas  a real folder cannot.  A few
+special NEWS groups, i.e. JUNK and CONTROL, do not contain a period.  If
+desired,  you can select these groups by enclosing them in double quotes
+("), and typing the name in lower case.
+
+A useful way to scan through folders or subscribed news group without 
+having to select them manually is to use the INDEX command.
+2 /MARKED
+Selects  only messages that have been marked (indicated by an asterisk).
+After using /MARKED, in order to see all messages, the folder will  have
+to be reselected.
+2 /UNMARKED
+Specifies to read only messages that have not been marked (marked
+messages are indicated by an asterisk).  
+
+After using, in order to see all messages, the folder will  have
+to be reselected.
+2 /SEEN
+Specifies to read only messages that have been seen (indicated by a
+greater than sign).
+
+After using, in order to see all messages, the folder will  have
+to be reselected.
+2 /UNSEEN
+Specifies to read only messages that have not been seen (seen message
+are indicated by a greater than sign).
+
+After using, in order to see all messages, the folder will  have
+to be reselected.
+1 SET
+The SET command  is  used  with  other  commands  to  define  or  change
+characteristics of the BULLETIN Utility.
+
+  Format:
+
+    SET option
+2 ACCESS
+Controls  access  to  a  private  folder.   A private folder can only be
+selected by users who have been granted access.  Only the owner of  that
+folder is allowed to grant access.
+
+  Format:
+
+    SET [NO]ACCESS id-name [folder-name]
+
+The id-name can be one or more ids from the system Rights  Database  for
+which  access  is  being  modified.   It  can  also be a file name which
+contains a list of  ids.   For  more  information  concerning  usage  of
+private  folders, see HELP CREATE /PRIVATE.  NOTE: Access is created via
+ACLs.  If a user's process privileges are set  to  override  ACLs,  that
+user  will  be  able  to  access  the folder even if access has not been
+granted.
+
+It  is suggested that if you plan on granting access to many users, that
+you create an id using the AUTHORIZE utility and then use the SET ACCESS
+command  to  grant  access  to  that id.  Then, you can use the GRANT/ID
+command in AUTHORIZE to grant the id to users, and this will give  those
+users  access to the folder.  This is preferred because of problems with
+running into system quota when checking for acls on a file with a  large
+amount  of  acls.   It  is also means that you don't have to remember to
+remove the access for that user from a folder if that  user  is  removed
+from the system.
+
+A user with BULLETIN privileges (see HELP SET  PRIV)  will  be  able  to
+select a protected folder regardless of the access settings.  However, a
+user without explicit access will not receive login notifications of new
+messages,  and thus will not be able to set any login flags.  (NOTE:  If
+such a user selects such a folder and then uses SET ACCESS to grant  him
+or  herself  access,  the user must reselect the folder in order for the
+new access to take affect in order to be able to set login flags.)
+3 id
+The id-name can be one or  more  ids  contained  in  the  system  Rights
+Database.    This  includes  usernames  and  UICs.    UICs  can  contain
+wildcards, i.e.  [130,*].  Note that by default, a process is given  the
+process  rights  id  SYS$NODE_nodename,  where  nodename  is  the decnet
+nodename.  Thus, by specifing this id, a folder can be restricted  to  a
+specific  node, which is useful when the folder is shared among nodes in
+a cluster. 
+
+Alternatively,  the  id-name  can be a filename which contains a list of
+ids.  The filename should be preceeded by a "@".  If the suffix  is  not
+specified, it will be assumed that the suffix is ".DIS" .
+3 /ALL
+Specifies that access to the folder is granted to all users.   If  /READ
+is  not  specified,  the  folder will no longer be private.  If /READ is
+specified, all users will have read access, but  only  privileged  users
+will  have  write access (of course non-privileged users can gain access
+via a later SET ACCESS command.)
+
+Format:
+
+    SET ACCESS /ALL [folder-name]
+3 /CLASS
+Specifies that the specified folder is a news group class.
+3 /READ
+Specifies that access to the folder will be limited to being able to
+read the messages.
+3 Warning
+If  a  user  logs  in after a private folder has been created but before
+being given access, and then is given  access,  any  defaults  that  the
+folder  has,  i.e. /BRIEF, /READNEW, & /NOTIFY, will not be set for that
+user. This is because if the  id  is  not  a  username,  it  becomes  an
+extremely  lengthy  operation  to check each user to see if have that id
+assigned to them.  The alternative is to set the defaults for all  users
+after  every  SET  ACCESS,  but that might cause problems with users who
+have manually reset those defaults.  The  correct  solution  requires  a
+large programming modification, which will be done in a later version.
+2 ANONYMOUS
+Specifies that the selected folder has the ANONYMOUS  attribute.    This
+causes  messages  in  the  folder  to  be  displayed  with  the username
+ANONYMOUS rather than the actual user's name.
+
+  Format:
+
+    SET [NO]ANONYMOUS
+2 ALWAYS
+Specifies  that  the  selected  folder  has  the ALWAYS attribute.  This
+causes messages in the folder to be displayed differently  when  logging
+in.  SYSTEM messages will be displayed every time a user logs in, rather
+than just once.  Non-SYSTEM message will also be  displayed  every  time
+(in  whatever  mode  is selected, i.e. BRIEF, SHOWNEW, or READNEW) until
+the user actually reads that message (or a later one).  This feature  is
+meant  for  messages which are very important, and thus you want to make
+sure they are read.
+
+  Format:
+
+    SET [NO]ALWAYS
+2 ADD_ONLY
+Specifies that the selected folder  has  the  ADD_ONLY  attribute.    If
+ADD_ONLY  is  set  and  a mailing address is present (see /DESCRIPTION),
+when a message is added to the folder, it will also  be  mailed  to  the
+address  (in addition to being stored in the folder).  This also applies
+to a message which is added via the BBOARD feature .  If ADD_ONLY is set
+and  a user uses the POST command, the ADD command will be used instead.
+One use for this is to mail messages in a folder to  users  who  do  not
+have access to BULLETIN. 
+
+  Format:
+
+    SET [NO]ADD_ONLY
+2 BBOARD
+Specifies  a username to be used as a BBOARD destination.  Mail which is
+sent to that user are converted into messages.  This command will  apply
+to  the  selected folder, and each folder can have its own BBOARD.  Only
+privileged users or owners of the folders can  set  BBOARD.   Note:  The
+specified  account  must  have  the DISUSER flag specified in the system
+authorization file, and it either must be given  SYSPRV  privileges,  or
+the  scratch  bboard_directory  (specified when compiling BULLETIN) must
+have world rwed  protection.   Also,  certain  system  parameters  which
+affect  detached  subprocesses  are  usually  too low for the subprocess
+which is spawned to read the mail.  The  parameters  and  the  suggested
+values  are:  PQL_DPGFLQUOTA = 15000, PQL_DWSQUOTA = 500, and PQL_DFILLM
+= 30.  If you are not using the BULLCP process, the subprocess limit for
+users must be at least 2.
+
+  Format:
+
+    SET BBOARD [username]
+
+BBOARD cannot be set for remote folders.   See  also  the  commands  SET
+STRIP and SET DIGEST for options on formatting BBOARD messages.
+
+If BULLCP is running, BBOARD is updated every 15 minutes.  If you want
+to length this period, define BULL_BBOARD_UPDATE to be the number of
+minutes, between updates.  I.e. DEFINE/SYSTEM BULL_BBOARD_UPDATE "30"
+will cause the updates to be don every 30 minutes.
+
+NOTE: If you want to control the expiration date on a per message basis,
+you can do so by adding a special header line to the message.  The form
+is Expires: or X-Expires: followed by the date in the form DD MMM YYYY.
+The time will always be 00:00, even if the time is specified on the line.
+3 /EXPIRATION
+ /EXPIRATION=days
+ /NOEXPIRATION
+
+Specifies the number of days the message created by the BBOARD is to  be
+retained.   The  default  is  14  days.   The  highest limit that can be
+specified is 30 days.  This can be overridden by a user with privileges.
+If /NOEXPIRATION is specified, messages will become permanent.
+
+NOTE:  This  value is the same value as specified by SET DEFAULT_EXPIRE.
+If one is changed, the other will change also.
+3 /SPECIAL
+Specifies that the input should be processed  using  a  special  command
+procedure,  and  not  to  use the simple VMS MAIL to message conversion.
+Specifying a username is optional.  To remove  this  feature,  you  must
+either  SET  NOBBOARD,  or  SET  BBOARD  and  specify  a  username.  See
+installation notes for exactly how to use this feature.
+3 /VMSMAIL
+Used in conjunction with  /SPECIAL.   If  /SPECIAL  and  a  username  is
+specified,  and the conversion still takes its input from VMS MAIL, then
+the VMS system mail file is checked to see if new mail  exists  for  the
+specified  user  before  running the command procedure.  This saves time
+and avoids creating subprocesses.  (Useful if input is digest format.)
+3 Listserv
+For a LISTSERV mailing list, only a subscribed user can post to it.   If
+the  BBOARD  account  is subscribed to the list in order for BULLETIN to
+receive the list, only the BBOARD account will be able to  post  to  it.
+This  problem  is  solved  by  placing  the  word LISTSERV in the folder
+description line. Then, messages sent to the mailing list  by  the  POST
+command will be sent from the BBOARD account rather than from the user's
+account.  For example, the folder description might be:
+
+FAKE MAILING LIST <FAKELIST@FAKENODE.BITNET> LISTSERV.
+
+If  you  have  PMDF  or  MX  installed,  the  corresponding logical name
+PMDF_REPLY_TO or MX_REPLY_TO will be temporarily defined in order to add
+a  REPLY-TO:   line  to  the  message  header to display the real user's
+address.
+
+Users  who  use the method described in HELP SET BBOARD MORE_INFORMATION
+should note the following:  When using this LISTSERV feature, the BBOARD
+account  must be a real account, not simply a VMS MAIL forwarding entry.
+Mail can only be sent from a real account.  However, if mail  forwarding
+is  set for that the account, the account does not need a real directory
+or a unique uic, since it will not need space to store mail.
+
+In order to be able to send LISTSERV commands from  the  BBOARD  account
+without  having  to  actually  login  to  the BBOARD account, there is a
+utility included with BULLETIN called SETUSER.  This requires privileges
+to use.  After compiling it, use the link command:
+
+        LINK SETUSER,SYS$SYSTEM:SYS.STB/SELECT
+
+When  you  run  it, it will prompt for a username.  After verifying that
+the given username  is  a  valid  account,  it  will  then  change  your
+process's username.  You can then send mail from that account.
+
+If you are using PMDF or MX, and wish to use this feature, you can still
+do  so  by  setting BBOARD.  As long as the BBOARD account is not a real
+account, it will work properly, even though the mail feed is not  really
+coming from the BBOARD account.
+
+In order to find out if the LISTSERV mailing list will accept posts only
+from subscribed users, send  the  command  'REV  listname'.   This  will
+retrieve the file listname.LIST.  It begins with a list of keywords.  If
+the keyword 'send' is set  to  'public',  you  don't  need  to  set  the
+LISTSERV  switch.   If it's set to 'private', you do.  For a description
+of the keywords and the meaning of their settings, send any LISTSERV the
+command  'INFO  KEY'. Note that the 'listname.LIST' files include a list
+of owners and subscribers.  If 'send' is set to 'owners',  then  neither
+the public nor the subscribers can post to the list.
+
+Note: It has been found that some servers don't accept the mail as being
+from the bboard account if the reply-to: line is added.  This might be
+due to it being run on VMS, where the Reply-to: line is converted to the
+From: line.  In this case, specify VMSSERV instead of LISTSERV.
+3 More_information
+If more than one folder is to have a BBOARD setting,  only  one  of  the
+BBOARD  names  need  be  a real account.  All other names could be names
+whose mail is  forwarded  to  the  real  account.   BULLETIN  will  then
+determine  from  the mail header which folder the mail is to be sent to.
+Forwarding can be enabled for any name within MAIL by the command:
+
+    MAIL> SET FORWARD/USER=from_name to_name
+
+Any  mail  sent  to  FROM_NAME will be forwarded to TO_NAME.  Thus, only
+TO_NAME need be a real account.  For example, if you  have  INFOVAX  and
+LASER-LOVERS  folders,  you need create only a INFOVAX account, and then
+forward LASER-LOVERS mail to INFOVAX within mail using the  command  SET
+FORWARD/USER=LASER-LOVERS  INFOVAX.   You  would  then  do  a SET BBOARD
+INFOVAX for the INFOVAX folder, and  SET  BBOARD  LASER-LOVERS  for  the
+LASER-LOVERS  folder.   This method will speed up the BBOARD conversion,
+since mail need be read only from one account.  NOTE: Folders that  have
+the  /SPECIAL  set  on  their  BBOARD  accounts  cannot  have their mail
+forwarded to BBOARD accounts that don't have /SPECIAL set.   Folders  of
+the  same  type, i.e. that use the same /SPECIAL command procedure, must
+be grouped separately.
+
+The BBOARD account must match the mailing list name.  If you prefer  not
+to  have  them  match,  then  you must include the actual address of the
+mailing list in the folder description in  the  format  described  under
+HELP CREATE /DESCRIPTION.
+2 BRIEF
+Controls whether you will be alerted upon logging  that  there  are  new
+messages  in the currently selected folder.  A new message is defined as
+one that has been created since the last time you logged in or  accessed
+BULLETIN.   Note  the  difference between BRIEF and READNEW.  The latter
+causes a listing of the description of the new messages to be  displayed
+and  prompts  the user to read the messages.  Setting BRIEF will clear a
+READNEW setting (and visa versa).
+
+  Format:
+
+    SET [NO]BRIEF
+3 /ALL
+Specifies that the SET [NO]BRIEF option is the default for all users for
+the specified folder.  This is a privileged qualifier.
+3 /DEFAULT
+Specifies that the [NO]BRIEF option is the default for the specified
+folder.  This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).  Use /ALL to modify all users.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the option is to modified.  If not
+specified, the selected folder is modified. Valid only with NOBRIEF.
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that BRIEF is a permanent flag and cannot be changed by the
+individual, except if changing to SHOWNEW or READNEW.  This is a
+privileged qualifier.
+2 COMPRESS
+Specifies that messages added to the folder will be in compressed format.
+Data stored in this way will be 60-65% the size of normal folders.
+The compression algorithm is optimized for English text files and requires 
+very little cpu overhead.
+
+  Format:
+
+    SET [NO]COMPRESS
+
+This command is only valid with folders.  Local news groups are always
+stored in compressed format.  Messages already stored in the folder 
+can not presently be changed to compressed format. 
+2 CONTINUOUS_BRIEF
+Specifies that if BRIEF is set for a folder, and there are new messages,
+the notification message "there are new messages" will be displayed every
+time when logging in, until the new messages are read.  Normally, the
+BRIEF setting causes notification only at the first time that new messages
+are detected.
+
+  Format:
+
+    SET [NO]CONTINUOUS_BRIEF
+
+NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the
+same user.
+2 DEFAULT_EXPIRE
+Specifies  the  number  of days the message created by BBOARD (or direct
+PMDF path) is to be retained.  The default  is  14  days.   The  highest
+limit  that  can  be  specified is 30 days.  This can be overridden by a
+user with privileges.
+
+This  also  specifies the default expiration date when adding a message.
+If no expiration date is  entered  when  prompted  for  a  date,  or  if
+prompting  has been disabled via SET NOPROMPT_EXPIRE, this value will be
+used.
+
+  Format:
+
+    SET DEFAULT_EXPIRE days
+
+If -1 is specified, messages will become permanent.  If 0 is  specified,
+no  default expiration date will be present.  The latter should never be
+specified for a  folder  with  a  BBOARD,  or  else  the  messages  will
+disappear.
+
+NOTE: This value is the same value that SET BBOARD/EXPIRATION specifies.
+If one is changed, the other will change also.
+2 DIGEST
+Affect  only  messages  which are added via either the BBOARD option, or
+written directly from a network mailing program  (i.e.  PMDF).   Several
+mailing  lists  use  digest  format  to  send  their  messages, i.e. the
+messages are concatenated into one long message.  If DIGEST is set,  the
+messages will be separated into individual BULLETIN messages.
+
+  Format:
+
+    SET [NO]DIGEST
+
+The command SHOW FOLDER/FULL will show if DIGEST has been set.
+
+2 DUMP
+Specifies that messages deleted from the  selected  folder  are  written
+into  a dump (or log) file.  The name of the log file is foldername.LOG,
+and it is located in the folder directory (usually BULL_DIR).
+
+  Format:
+
+    SET [NO]DUMP
+
+The command SHOW FOLDER/FULL will show if dump has  been  set.    (NOTE:
+SHOW  FOLDER/FULL  is a privileged command.) When created, the file will
+have an ACL set on it to allow the folder owner to delete it.
+2 EXPIRE_LIMIT
+Specifies expiration limit that is allowed for messages.  Non-privileged
+users cannot specify an expiration  that  exceeds  the  number  of  days
+specified.  Privileged users can exceed the limit.
+
+  Format:
+
+    SET [NO]EXPIRE_LIMIT [days]
+
+The command SHOW FOLDER/FULL will show  the  expiration  limit,  if  one
+exists.  (NOTE: SHOW FOLDER/FULL is a privileged command.) 
+2 EXCLUDE
+Specifies to ignore any EXCLUDEs or THREADs that are present.
+
+  Format:
+
+    SET [NO]EXCLUDE
+
+The default mode is SET EXCLUDE, which means to display  messages  based
+on  specified  EXCLUDEs  or  THREADs.    SET  NOEXCLUDE  will cause all
+messages to be displayed for the selected folder, and all future folders
+which are selected. 
+2 EXLIMIT
+Specifies the default limit for the EXCLUDE command. 
+
+  Format:
+
+    SET EXLIMIT days
+
+If no match is found for an exclude after the specified number of  days,
+the  exclude  will  automatically  be deleted.  The default is no limit,
+which is specified by specifying 0 days.  This default can be  overriden
+by the /LIMIT switch on the EXCLUDE command. 
+2 FILE_DIRECTORY
+Select the directory where  messages  are  written  to  when  using  the
+EXTRACT  or  file  COMMAND.  By default, the message is written into the
+current directory. 
+
+  Format:
+
+    SET FILE_DIRECTORY [directory]
+
+If directory is omitted, the setting is removed.  Note: This information
+is stored in the customization file (SYS$LOGIN:BULL.CUSTOM).
+2 FOLDER
+Select a folder of messages.  Identical to the SELECT command.  See help
+on that command for more information.
+
+  Format:
+
+    SET FOLDER [node-name::][folder-name]
+3 /MARKED
+Selects messages that have been marked (indicated by an asterisk).
+After using /MARKED, in order to see all messages, the folder will have
+to be reselected.
+2 GENERIC
+Specifies  that  the  given  account is a "generic" account, i.e used by
+many different people.  If an  account  is  specified  as  GENERIC,  new
+messages  placed in the default folder will be displayed upon logging in
+for a specific number of days,  rather  than  only  once.   The  default
+period is 7 days.  This command is a privileged command.
+
+  Format:
+
+    SET [NO]GENERIC username
+
+NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the
+same user.
+3 /DAYS
+ /DAYS=number_of_days
+
+Specifies the number days that new messages will be displayed for upon
+logging in.
+2 GATEWAY
+Valid for folders that are associated with an email address.    Messages
+which  are  mailed  to the email address are by default modified so that
+the subject line starts with the folder name,  followed  by  the  phrase
+"folder  message:  ",  followed  original  subject line.  If you specify
+GATEWAY, the subject line is not modified this way. 
+2 KEYPAD 
+Controls whether the keypad has been enabled such that the keys  on  the
+keypad correspond to command definitions.  These definitions can be seen
+via the SHOW KEYPAD command.  The default is NOKEYPAD unless the /KEYPAD
+qualifier has been added to the BULLETIN command line.
+
+  Format:
+
+    SET [NO]KEYPAD
+
+The default settings  for the keypad are shown via SHOW KEYPAD or HELP
+KEYPAD.  Settings can be  changed by using an initialization file with
+DEFINE/KEY commands.  BULLETIN looks first for the file pointed to by
+the logical name BULL_INIT and  then for the file SYS$LOGIN:BULL.INI.
+2 LIBRARY
+Specifies a library of folders.  By default there is only  one  library.
+However,  the system manager may decide to create more than one library,
+with each library  saved  in  a  different  directory.    Use  the  SHOW
+LIBRARY/ALL command to see if there are other libraries. 
+2 LOGIN
+Controls  whether  the  specified  user will be alerted of any messages,
+whether system or non-system, upon logging in.  If an  account  has  the
+DISMAIL  flag  set, SET NOLOGIN is automatically applied to that account
+during the first time that the account logs in.  However, this will  not
+occur  if DISMAIL is set for an old account.  Additionally, removing the
+DISMAIL flag will not automatically enable LOGIN.  (The reason  for  the
+above  was to avoid extra overhead for constant checking for the DISMAIL
+flag.)  This command is a privileged command.
+
+  Format:
+
+    SET [NO]LOGIN username
+2 NAME
+Copies all stored settings from one user to another.  Used when a user's
+account name is changed.
+
+  Format:
+
+    SET NAME old-username new-username
+2 NEWS
+Changes attributes of the specified news group or class of news groups.
+This command requires privileges.
+
+  Format:
+
+    SET NEWS [news-group]
+
+If no attributes are specified, the present values of the attributes are
+shown.
+3 /ALL
+   /ALL
+   /NOALL
+
+If specified with /CLASS or /DEFAULT, all groups that are presently
+available will have their attributes changed,in addition to any that are
+created in the future.  If /NOALL is specified, the attributes of any
+news group that was individually changed will not be modified.  I.e., if
+you set the attributes for misc.test, and then change the default
+attributes (using /DEFAULT) with /NOALL, the attributes for misc.test
+will not be changed.  This also applies when specifying the attributes
+for a class of news groups with /CLASS, but only if the value for /CLASS
+is a primary class, i.e. it has a no period in the classname such as
+CLASS=rec.  Otherwise, /NOALL is not allowed with /CLASS.  The default
+is /ALL.                                     
+3 /CLASS
+   /CLASS=classname
+
+Specifies to modify attributes for a class of news groups rather than a
+single group, i.e. /CLASS=rec, or /CLASS=sci.med .  Attributes of
+existing groups which are in the class are modified, and any groups
+created in the future will automatically have those attributes.
+3 /DEFAULT
+Specifies default attributes which are applied to all news groups.
+3 /DELETE
+When used with /CLASS, specifies that the class attributes are to be
+deleted.
+3 /DISABLE
+Specifies that the news group is disabled and can not be accessed.
+3 /ENABLE
+Specifies that the news group is enabled and can be accessed. This is
+the default.
+3 /EXPIRATION
+   /EXPIRATION=days
+
+Specifies the default expiration time for messages if none is specified.
+The default is 7.
+3 /FULL
+Control whether all information of the news groups  is  displayed,  i.e.
+the  access list if the news group is private.  This information is only
+those who have access to that folder. 
+3 /LIMIT
+   /LIMIT=days
+
+Specifies the expiration limit for messages.  If the value specified is
+-1, there will be no limit.  If the value is 0, the default limit will
+be applied, or of any class that is applicable.  This is the default.
+It is suggested that the limit be set a no lower than 31 days, as many
+groups have a FAQ (frequently asked question) message which is posted
+every month with an expiration date of one month in the future.
+3 /PRIVATE
+   /PRIVATE
+   /NOPRIVATE
+
+Specifies that the news group or class can have it's access modified by
+the SET ACCESS command.  To accomplish this, a file is created in
+NEWS_DIRECTORY specified in BULLFILES.INC and ACLs are set on that file.  
+Note:  If you set access for a class, the best way to grant all access 
+to news groups in that class is to set /NOPRIVATE, as then time won't be 
+wasted checking a file for ACLs.
+3 /STORED
+   /STORED
+   /NOSTORED
+
+Specifies that the news group are stored on disk rather then accessed
+via the network from the server node.  This results in faster access,
+but requires the available disk space.  Messages from the news group
+are not immediately transferred as the result of this command, but are
+tranferred by the separate BULLCP process at regular intervals.  The
+default is /NOSTORED.
+2 NODE
+Modifies the selected folder from a local folder to a remote folder.   A
+remote folder is a folder in which the messages are actually stored on a
+folder at a remote DECNET node.  The SET NODE command specifies the name
+of  the  remote  node, and optionally the name of the remote folder.  If
+the remote folder name is not included, it is assumed to be the same  as
+the  local  folder.   When  the command is executed, the selected folder
+will then point to the remote folder.  If there  were  messages  in  the
+local folder, they will be deleted.  This feature is present only if the
+BULLCP process is running on the remote node.
+
+  Format:
+    SET NODE nodename [remotename]
+    SET NONODE
+
+NOTE: If one node adds a message to a remote node, other nodes connected
+to the same folder will not immediately be aware  of  the  new  message.
+This  info  is  updated  every  15  minutes,  or if a user accesses that
+folder.
+
+If you are using V2.16 or greater on both nodes, then if the data files 
+of the node containing the remote folder are moved to a different node,
+(or if you decided to start BULLCP on a different nooe in that cluster),
+the nodename of the remote folders will automatically be updated.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the node information is to modified.
+If not specified, the selected folder is modified.
+2 NOTIFY
+Specifies whether you will be notified via a broadcast  message  when  a
+message is added to the selected folder.
+
+  Format:
+
+    SET [NO]NOTIFY
+
+In a cluster, if the logical name MAIL$SYSTEM_FLAGS is defined so that
+bit 1 is set, users will be notified no matter which node they are logged
+in to.  If you wish to disable this, you should define BULL_SYSTEM_FLAGS
+so that bit 1 is cleared.
+3 /ALL
+Specifies that the SET [NO]NOTIFY option is the default for all users for
+the specified folder.  This is a privileged qualifier.
+3 /DEFAULT
+Specifies that the [NO]NOTIFY option is the default for the specified
+folder.  This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).  Use /ALL to modify all users.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the option is to modified.  If not
+specified, the selected folder is modified. Valid only with NONOTIFY.
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that NOTIFY is a permanent flag and cannot be changed by the
+individual. /DEFAULT must be specified. This is a privileged qualifier.
+2 PAGE
+Specifies whether any directory listing or message reading  output  will
+pause  when  it  reaches  the end of the page or not.  Setting NOPAGE is
+useful for terminals that can store more than one screenful at  a  time,
+and  that  have a remote printer that can then print the contents of the
+terminal's memory.  The default is PAGE, unless the default was  changed
+by specifying /NOPAGE on the command line to invoke BULLETIN.
+
+  Format:
+
+    SET [NO]PAGE
+2 POST_ONLY
+Specifies that the selected folder has the POST_ONLY attribute.  This
+causes the ADD command to mail the message to the mailing address if it
+is present (see /DESCRIPTION), rather than add to the folder.  
+
+  Format:
+
+    SET [NO]POST_ONLY
+2 PRIVILEGES
+Specifies  either  process  privileges  or  rights  identifiers that are
+necessary to use privileged commands.  Use the SHOW  PRIVILEGES  command
+to see what is presently set.  This is a privileged command.
+
+  Format:
+
+    SET PRIVILEGES parameters
+
+The parameters are one or  more  privileges  separated  by  commas.   To
+remove  a privilege, specify the privilege preceeded by "NO".  If /ID is
+specified, the parameters are rights identifiers.
+3 /ID
+ /[NO]ID
+
+If specified, then the rights identifier which is specified as the
+parameter will allow users holding that rights identifier to execute
+privileged commands.  If /NOID is specified, the identifier is removed.
+2 PROMPT_EXPIRE
+Specifies  that  a  user  will  be  prompted for an expiration date when
+adding a message.  If NOPROMPT_EXPIRE is specified, the user will not be
+prompted, and the default expiration (which is set by SET DEFAULT_EXPIRE
+or SET BBOARD/EXPIRATION) will be  used.   If  the  value  specified  is
+greater   than  the  expiration  limit,  and  the  user  does  not  have
+privileges, then the expiration  limit  will  be  used  as  the  default
+expiration.  (If there is no expiration limit, and the user doesn't have
+privileges, then an error will result.)  PROMPT_EXPIRE is the default.
+
+  Format:
+
+    SET  [NO]PROMPT_EXPIRE
+2 READNEW
+Controls whether you will be prompted upon logging in  if  you  wish  to
+read new non-system or folder messages (if any exist).  A new message is
+defined as one that has been  added  since  the  last  login,  or  since
+accessing BULLETIN.  The default setting for READNEW is dependent on how
+the folder was created by the owner.
+
+In  order  to  apply  this to a specific folder, first select the folder
+(using the SELECT command), and then enter the SET READNEW command.
+
+  Format:
+
+    SET [NO]READNEW
+
+NOTE:  If  you  have several folders with READNEW enabled, each folder's
+messages will be displayed separately.  However, if you EXIT the READNEW
+mode before all the folders have been displayed, you will not be alerted
+of the new messages in the undisplayed folders the next time you  login.
+However,  if  you enter BULLETIN, you will be told that new messages are
+present in those other folders.  Also, it is not possible  to  EXIT  the
+READNEW mode if there are SYSTEM folders which have new messages. Typing
+the EXIT command will cause you to skip to those folders.  (See HELP SET
+SYSTEM for a description of a SYSTEM folder).
+3 /ALL
+Specifies that the SET [NO]READNEW option is the default for all users for
+the specified folder.  This is a privileged qualifier.  The difference
+between this and /DEFAULT is that the latter will only apply to new users
+(i.e. any users which have never executed BULLETIN).
+3 /DEFAULT
+Specifies that the [NO]READNEW option is the default for the specified
+folder.  This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).  Use /ALL to modify all users.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the option is to modified.  If not
+specified, the selected folder is modified. Valid only with NOREADNEW.
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that READNEW is a permanent flag and cannot be changed by the
+individual.  This is a privileged qualifier.
+2 SHOWNEW
+Controls whether a directory listing of new  messages  for  the  current
+folder  will  be displayed when logging in.  This is similar to READNEW,
+except you will not be prompted to read the messages.   The  default  is
+dependent  on how the folder was created by the owner.  A new message is
+defined as one that has been  added  since  the  last  login,  or  since
+accessing BULLETIN.
+
+In order to apply this to a specific folder,  first  select  the  folder
+(using  the  SELECT  command),  and  then enter the SET SHOWNEW command.
+
+  Format:
+
+    SET [NO]SHOWNEW
+3 /ALL
+Specifies that the SET [NO]SHOWNEW option is the default for all users for
+the specified folder.  This is a privileged qualifier.  The difference
+between this and /DEFAULT is that the latter will only apply to new users
+(i.e. any users which have never executed BULLETIN).
+3 /DEFAULT
+Specifies that the [NO]SHOWNEW option is the default for  the  specified
+folder.   This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).   Use  /ALL  to  modify  all
+users. 
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the  option  is  to  modified.    If  not
+specified, the selected folder is modified. Valid only with NOSHOWNEW. 
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that SHOWNEW is a permanent flag and cannot be changed by  the
+individual,  except  if  changing  to  READNEW.  This  is  a  privileged
+qualifier. 
+2 STRIP
+Affect only messages which are added via either the  BBOARD  option,  or
+written  directly  from a network mailing program (i.e. PMDF).  If STRIP
+is set, the header of the mail message will be stripped off before it is
+stored as a BULLETIN message. 
+
+  Format:
+
+    SET [NO]STRIP
+
+The command SHOW FOLDER/FULL will show if STRIP has been set.
+2 SUBSCRIBE
+Can be used to force users to be subscribed to the selected news  group.
+This is a privileged command. 
+
+  Format:
+
+    SET SUBSCRIBE
+
+Note:  If you execute the  commands  SET  SHOWNEW,  READNEW,  BRIEF,  or
+NOTIFY,  and add /DEFAULT or /PERMAMENT, it is equivalent to doing a SET
+SUBSCRIBE command with the addition that the specified feature  will  be
+the default and/or permanent setting. 
+3 /ALL
+Specifies that all present and future users will be  subscribed  to  the
+news group. 
+3 /DEFAULT
+   /[NO]DEFAULT
+
+Specifies that new users will automatically be subscribed  to  the  news
+group. 
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that new users will automatically be subscribed  to  the  news
+group and that users cannot unsubscribe the news group. 
+2 SYSTEM
+Specifies that the selected folder is a SYSTEM folder.  A SYSTEM  folder
+is  allowed to have SYSTEM and SHUTDOWN messages added to it.  This is a
+privileged command. 
+
+  Format:
+
+    SET [NO]SYSTEM
+
+If the selected folder is remote, /SYSTEM cannot be specified unless the
+folder at the other node is also a SYSTEM folder.
+1 SHOW
+The SHOW command displays information about certain characteristics.
+2 EXCLUDE
+Displays the list of excludes which are present for the current  folder.
+The  right  hand  side  of the display shows the date of the last time a
+match for the exclude was found, and also the number of  days  from  the
+time of the last match after which the excludes expires. 
+2 FLAGS
+Shows whether BRIEF, NOTIFY, READNEW, or SHOWNEW has been  set  for  the
+currently selected folder. 
+2 FOLDER
+Shows information about a folder of messages.  Owner and description are
+shown.    If  the folder name is omitted, and a folder has been selected
+via the SELECT command, information about that folder is shown. 
+
+  Format:
+
+    SHOW FOLDER [folder-name]
+3 /FULL
+Control whether all information  of  the  folder  is  displayed.    This
+includes  DUMP  &  SYSTEM  settings,  the  access  list if the folder is
+private, and BBOARD information.  This information  is  only  those  who
+have access to that folder. 
+2 THREAD
+Displays the list of includes which are present for the current folder.
+2 KEYPAD
+Displays the keypad command definitions.
+
+  Format:
+
+    SHOW KEYPAD [key-name]  
+
+If the keypad has been enabled by either SET KEYPAD, or  if  /KEYPAD  is
+specified  on  the  command  line,  the  keypad  keys will be defined as
+commands.  The default settings for the keypad are shown via SHOW KEYPAD
+or HELP KEYPAD.  Settings can be changed by using an initialization file
+with DEFINE/KEY commands.  BULLETIN looks first for the file pointed  to
+by the logical name BULL_INIT and then for the file SYS$LOGIN:BULL.INI. 
+
+NOTE: If the keypad is not enabled, PF2 is defined to be SET KEYPAD.
+3 /PRINT
+Prints the keypad definitions on the default printer (SYS$PRINT).
+3 /STATE
+ /STATE=(state,state,...)
+
+Specifies the name of a state for which the  specified  key  definitions
+are  to  be displayed.  If you select more than one state name, separate
+them with commas and enclose the list in parentheses.  Only works when a
+key name has been specified. 
+2 LIBRARY
+Shows the library of folders.  By default there  is  only  one  library.
+However,  the system manager may decide to create more than one library,
+with each library  saved  in  a  different  directory.    Use  the  /ALL
+qualifier to see if there are other libraries. 
+3 /ALL
+Specifies to show all available libraries.
+2 NEW
+Shows folders which have new unread messages for which BRIEF or  READNEW
+have  been set.  (Note: If you enter BULLETIN but do not read new unread
+messages, you will not be notified about them the next  time  you  enter
+BULLETIN.  This is a design "feature" and cannot easily be changed.)
+2 PRIVILEGES
+Shows the privileges necessary to use privileged commands.   Also  shows
+any  rights  identifiers  that  would also give a user privileges.  (The
+latter are ACLs which are set on the BULLUSER.DAT file.)
+2 USER
+Shows the last time that a user logged in, or if /FOLDER  is  specified,
+the  latest  message which a user has read in the folder.  If NOLOGIN is
+set for  a  user,  this  information  will  be  displayed.   This  is  a
+privileged  command.   Non-privileged users will only be able to display
+the information for their own account.
+
+  Format:
+    SHOW USER [username]
+
+The username is optional.  If omitted, the process's username  is  used.
+The  username should not be included if /ALL or /[NO]LOGIN is specified.
+
+NOTE: The last logged in time displayed is that which is stored when the
+BULLETIN/LOGIN command is executed, not that  which  VMS  stores.   Some
+sites  make  BULLETIN/LOGIN  an  optional  command for users to store in
+their own LOGIN.COM, so this command can be used  to  show  which  users
+have done this.
+3 /ALL
+Specifies that information for all users is to be displayed.  This is  a
+privileged command.
+3 /LOGIN
+ /[NO]LOGIN
+
+Specifies that only those users which do not have NOLOGIN set are to be
+displayed.  If negated, only those users with NOLOGIN set are displayed.
+This is a privileged command.  The qualifier /ALL need not be specified.
+3 /FOLDER
+   /FOLDER=[foldername]
+
+Specifies to display the latest message that was read by the user(s) for
+the  specified  foldername.   A newsgroup can be specified, but the info
+can only be shown if the user has subscribed to the newsgroup.   If  the
+foldername is not specified, the selected folder will be used.
+3 /SINCE
+   /SINCE=[date]
+
+Specifies  to display only those users whose latest read message date is
+the same date  or  later  than  the  specified  date.   If  no  date  is
+specified,  the  date  of  the  current message is used.  Only valid for
+folders or with /LOGIN.  Use /START for newsgroups.
+3 /START
+   /START=[number]
+
+Specifies  to  display only those users whose latest read message number
+is equal to or greather than the specified  number.   If  no  number  is
+specified,  the  message  number  of  the current message is used.  Only
+valid for newsgroups.  Use /SINCE for folders and with /LOGIN.
+2 VERSION
+Shows  the  version  of  BULLETIN  and  the date that the executable was
+linked.
+1 SPAWN
+Creates  a  subprocess  of  the current process.  To return to BULLETIN,
+type LOGOUT.
+
+  Format:
+    SPAWN [command-string]
+
+NOTE: BULLETIN disables the use of  CONTROL-C,  so  that  you  must  use
+CONTROL-Y if you wish to break out of a spawned command.
+1 SUBSCRIBE
+Used only for NEWS folders.  Specifies that BULLETIN will keep track  of
+the  newest  message  that has been read for that NEWS folder.  When the
+NEWS folder is selected, the message pointer will automatically point to
+the next newest message that has not been read.  To see a list of the
+subscribed groups, type NEWS/SUBSCRIBE.  To automatically read news 
+groups with new messages, use INDEX/SUBSCRIBE. 
+1 THREAD
+Specifies that the current message is  defined  as  a  thread  based  on
+either  the  subject  or the message owner.  Since threads are much more
+commonly based on the subject, this is the default.  Threads are read by
+using the command READ/THREADS. 
+
+  Format:
+    THREAD [string]
+
+If a string is specified, then the message is a thread if the  owner  or
+the subject contains that string, depending on whether /FROM or /SUBJECT
+is specified.  Otherwise, if no string is specified, then the owner name
+or  subject of the current message is used.  More than one THREAD may be
+specified per folder. 
+
+Note:  EXCLUDEs based on FROM will take precedence over THREADs.
+2 /ALL
+Used with /DISABLE to specify to disable all THREADs.
+2 /DISABLE
+Specifies to permanently disable the THREAD.
+2 /FROM
+Specifies to include the message based on the message owner.  /FROM
+and /SUBJECT cannot be specified at the same time. 
+2 /LIMIT
+   /LIMIT=days
+
+Specifies that the thread will be automatically deleted if no match  is
+found  for the specified number of days.  The default is no limit, which
+is specified by 0.  This can be changed via the SET EXLIMIT command. 
+2 /SUBJECT
+Specifies to include the message based on the message subject.  This is
+the default.  /FROM and /SUBJECT cannot be specified at the same time.
+2 Storing_Threads
+THREADs are stored in the file SYS$LOGIN:BULL.CUSTOM or in the file
+pointed to by the logical name BULL_USER_CUSTOM.  The format is:
+
+folder_name:INCLUDE:FROM(or SUBJECT):string
+
+In order for /FULL to be the default for a folder, the following line
+must be present:
+
+folder_name:defaults:kill
+
+excluding the folder_name causes it to apply to all folders.
+1 UNDELETE
+Undeletes  he  specified  message  if  the message was deleted using the
+DELETE command.  Deleted messages are  not  actually  deleted  but  have
+their  expiration  date  set to 15 minutes in the future and are deleted
+then.  Undeleting the message will reset the expiration date back to its
+original  value.   Deleted  messages  will  be  indicated as such by the
+string (DELETED) when either reading or doing a directory listing.
+
+  Format:
+    UNDELETE [message-number]
+1 UNSUBSCRIBE
+Used only for NEWS folders.  Specifies that BULLETIN will no longer keep
+track of the newest message that has been read for that NEWS folder.  See the
+SUBSCRIBE command for further info. 
+1 Usenet_news
+BULLETIN can also read USENET NEWS if your system has network access  to
+a node which carries it.  USENET NEWS is a global bulletin board system.
+It is split into news groups.  Use the NEWS command to see the  list  of
+groups  which  are  available.  These are similar to BULLETIN's folders,
+except that the SUBSCRIBE command must be used to subscribe to  a  group
+in  order  to  keep track of which messages you have read in that group.
+Most of the other BULLETIN commands can also be used when reading NEWS. 
+
+To see a list  of  the  subscribed  groups,  type  NEWS/SUBSCRIBE.    To
+automatically  read  all  your  subscribed  news  groups  that  have new
+messages, use INDEX/SUBSCRIBE. 
diff --git a/decus/vmslt00a/bulletin/bulldir.inc b/decus/vmslt00a/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..ab5027c65ee5187fc204f90472579883ae4c1d5b
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulldir.inc
@@ -0,0 +1,58 @@
+	PARAMETER DIR_RECORD_LENGTH = (100/4)*4
+
+	COMMON /BULL_DIR/ MSG_BTIM,MSG_NUM,DESCRIP,FROM,LENGTH,EX_BTIM
+     &	,SYSTEM,BLOCK,HEADER_BTIM,HEADER_NUM,NEWEST_EXBTIM,NEWEST_MSGBTIM
+     &	,NBULL,NBLOCK,SHUTDOWN,SHUTDOWN_BTIM,NEMPTY
+     &	,DATE,TIME,EXDATE,EXTIME,NEWEST_EXDATE,NEWEST_EXTIME
+     &  ,NEWEST_DATE,NEWEST_TIME,SHUTDOWN_DATE,SHUTDOWN_TIME
+	CHARACTER*56 DESCRIP
+	CHARACTER*12 FROM
+	LOGICAL SYSTEM
+
+	CHARACTER*12 DATE,EXDATE,NEWEST_EXDATE,NEWEST_DATE,SHUTDOWN_DATE
+	CHARACTER*12 TIME,EXTIME,NEWEST_EXTIME,NEWEST_TIME,SHUTDOWN_TIME
+
+	INTEGER MSG_BTIM(2),EX_BTIM(2),HEADER_BTIM(2)
+	INTEGER NEWEST_EXBTIM(2),NEWEST_MSGBTIM(2),SHUTDOWN_BTIM(2)
+
+	CHARACTER*(DIR_RECORD_LENGTH) BULLDIR_ENTRY
+	EQUIVALENCE (MSG_BTIM,BULLDIR_ENTRY)
+
+	CHARACTER*52 BULLDIR_HEADER
+	EQUIVALENCE (HEADER_BTIM,BULLDIR_HEADER)
+
+	DATA HEADER_BTIM/0,0/,HEADER_NUM/0/
+
+	CHARACTER MSG_KEY*8
+
+	EQUIVALENCE (MSG_BTIM,MSG_KEY)
+
+	PARAMETER LINE_LENGTH=255
+	PARAMETER INPUT_LENGTH=256
+
+	COMMON /INPUT_BUFFER/ INPUT
+	CHARACTER INPUT*(INPUT_LENGTH)
+
+	PARAMETER NEWSDIR_RECORD_LENGTH = 140
+
+	COMMON /NEWS_DIR/ NEWS_MSG_NUM,NEWS_MSG_BTIM_KEY
+     &  ,NEWS_EX_BTIM_KEY,NEWS_MSGID,NEWS_POST_KEY,NEWS_BLOCK
+     &  ,NEWS_LENGTH,NEWS_DESCRIP,NEWS_FROM
+     &  ,NEWS_HEADER_KEY,NEWS_NEWEST_MSG_BTIM_KEY
+     &  ,NEWS_HEADER_FOLDER,NEWS_NEWEST_EX_BTIM_KEY,NEWS_HEADER_NUM
+     &	,NEWS_NBULL
+	CHARACTER*36 NEWS_MSGID
+	CHARACTER*56 NEWS_DESCRIP
+	CHARACTER*12 NEWS_FROM
+	CHARACTER*8 NEWS_POST_KEY
+
+	CHARACTER*8 NEWS_MSG_BTIM_KEY,NEWS_EX_BTIM_KEY
+	CHARACTER*8 NEWS_NEWEST_MSG_BTIM_KEY,NEWS_NEWEST_EX_BTIM_KEY
+	INTEGER NEWS_POST_BTIM(2)
+
+	CHARACTER*(NEWSDIR_RECORD_LENGTH) NEWSDIR_ENTRY
+	EQUIVALENCE (NEWS_MSG_NUM,NEWSDIR_ENTRY)
+
+	CHARACTER*64 NEWS_HEADER_FOLDER
+	CHARACTER*(NEWSDIR_RECORD_LENGTH) NEWSDIR_HEADER
+	EQUIVALENCE (NEWS_HEADER_KEY,NEWSDIR_HEADER)
diff --git a/decus/vmslt00a/bulletin/bulletin.cld b/decus/vmslt00a/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..95c9f312f53857ea7afa22a5ab608ef937c0a222
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin.cld
@@ -0,0 +1,44 @@
+!
+!  This file is the CLD file used to define a command to execute
+!  BULLETIN by using CDU, which adds the command  to the command table.
+!  The alternative is to define a symbol to execute BULLETIN.
+!  Either way will work, and it is up to the user's to decide which
+!  method to work.  (If you don't know which, you probably should use
+!  the default symbol method.)
+!
+
+Define Verb BULLETIN
+  Image BULL_DIR:BULLETIN
+  Parameter P1, Label = SELECT_FOLDER, value(type=$quoted_string)
+  Qualifier ALL
+  Qualifier BBOARD
+  Qualifier BULLCP
+  Qualifier CLEANUP, Value (Required)
+  Qualifier EDIT
+  Qualifier KEYPAD, Default
+  Qualifier LIBRARY, Value (Required) 
+  Qualifier LOGIN
+  Qualifier MARKED
+  Qualifier PAGE, Default
+  Qualifier PGFLQUOTA, Value (Type = $NUMBER, Required)
+  Qualifier PROMPT, Value (Default = "BULLETIN"), Default
+  Qualifier READNEW
+  Qualifier REVERSE
+  !
+  ! The following line causes a line to be outputted separating system notices.
+  ! The line consists of a line of all "-"s, i.e.:
+  !--------------------------------------------------------------------------
+  ! If you want a different character to be used, simply put in the desired one
+  ! in the following line.  If you want to disable the feature, remove the
+  ! Default at the end of the line.  (Don't remove the whole line!)
+  !
+  Qualifier SEPARATE, Value (Default = "-"), Default
+  Qualifier SEEN
+  Qualifier STARTUP
+  Qualifier STOP
+  Qualifier SYSTEM, Value (Type = $NUMBER, Default = "7")
+  Qualifier UNMARKED
+  Qualifier UNSEEN
+  Qualifier WIDTH, Value (Type = $NUMBER, Required)
+  Qualifier WSEXTENT, Value (Type = $NUMBER, Required)
+  Disallow (WSEXTENT Or PGFLQUOTA) And Not STARTUP
diff --git a/decus/vmslt00a/bulletin/bulletin.for b/decus/vmslt00a/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..8b9ef63c23c879692137e4e7cdeabf7a8b28b21b
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin.for
@@ -0,0 +1,2129 @@
+C
+C  BULLETIN.FOR, Version 2/27/98
+C  Purpose: Bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	EXTERNAL BULLETIN_SUBCOMMANDS,LIB$GET_INPUT
+	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
+	CHARACTER*44 PROMPT
+
+	COMMON /NEXT_COMMAND/ NEXT_COMMAND
+	CHARACTER NEXT_COMMAND*64
+	DATA NEXT_COMMAND/' '/
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/
+
+	COMMON /DCL/ DCL_CMD,DCL_COMMAND
+	CHARACTER DCL_CMD*132
+
+	CALL INIT_BULLETIN(.TRUE.)
+
+C
+C  The MAIN loop for processing bulletin commands.
+C
+
+	LPROMPT = TRIM(COMMAND_PROMPT)
+	PROMPT = CHAR(10)//COMMAND_PROMPT(:LPROMPT)//' '
+	LPROMPT = LPROMPT + 2
+
+	DO WHILE (LPROMPT.GT.0)
+
+	   IF (.NOT.DCL_COMMAND) THEN
+	      CALL COMMAND_INPUT(IER)
+	   ELSE
+	      IF (INDEX(DCL_CMD,';').GT.0) THEN
+	         INCMD = DCL_CMD(:INDEX(DCL_CMD,';')-1)
+	         DCL_COMMAND = DCL_CMD(INDEX(DCL_CMD,';'):).NE.';'
+	         DCL_CMD = DCL_CMD(INDEX(DCL_CMD,';')+1:)
+	      ELSE
+	         INCMD = DCL_CMD
+	         DCL_CMD = ' '
+	      END IF
+ 	      IER = TRIM(INCMD)
+	   END IF
+
+	   IF (IER.EQ.-2) THEN
+	      IER = RMS$_EOF
+	   ELSE IF (IER.LE.0) THEN
+	      IER = %LOC(CLI$_NOCOMD)
+	   ELSE
+	      DO WHILE (IER.GT.0.AND.INCMD(:1).EQ.' ')
+		 INCMD = INCMD(2:IER)
+		 IER = IER - 1
+	      END DO
+	      IF (IER.GT.0.AND.INCMD(:1).GE.'0'.AND.INCMD(:1).LE.'9') THEN
+		 INCMD = 'READ '//INCMD
+	      END IF
+	      IF (IER.GT.0) THEN 
+		  IF (INDEX(INCMD(:IER),' ').EQ.0.AND.
+     &		      INDEX(INCMD,'/').EQ.0.AND.
+     &		      INDEX(INCMD,'.').GT.0) INCMD = 'SELECT '//INCMD
+	      END IF
+	      IER=CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS,LIB$GET_INPUT)
+	   END IF
+
+	   IF (IER.EQ.RMS$_EOF) THEN
+	      CALL EXIT			! If no command, exit
+	   ELSE IF (IER.EQ.%LOC(CLI$_NOCOMD)) THEN  ! If just RETURN entered
+	      INCMD = ' '		! Make sure there is none
+	      LEN_P = 0			! Indicate no parameter in command
+	      IF (DIR_COUNT.GT.0) THEN		! If still more dir entries
+		 CALL DIRECTORY(DIR_COUNT)	! continue outputting them
+	      ELSE IF (INDEX_COUNT.GT.0) THEN
+	         CALL FULL_DIR
+	      ELSE IF (FOLDER_COUNT.GT.0) THEN	! If more folder entries
+		 CALL DIRECTORY_FOLDERS(FOLDER_COUNT) ! continue outputting them
+	      ELSE IF (READ_COUNT.NE.0) THEN 
+		 CALL READ_MSG(READ_COUNT,BULL_POINT+1)
+	         DIR_COUNT = 0
+	         FOLDER_COUNT = 0
+	         INDEX_COUNT = 0
+	      ELSE IF (NEXT_COMMAND.NE.' ') THEN
+		 INCMD = NEXT_COMMAND
+	         IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS,LIB$GET_INPUT)
+		 CALL DO_COMMAND(INCMD)
+	      ELSE				! Else try to read next bulletin
+		 CALL READ_MSG(READ_COUNT,BULL_POINT+1)  ! or finish old one
+	         DIR_COUNT = 0
+	         FOLDER_COUNT = 0
+	         INDEX_COUNT = 0
+	      END IF
+	      GO TO 100				! Loop to read new command
+	   ELSE IF (.NOT.IER) THEN		! If command has error
+	      GO TO 100				! ask for new command
+	   END IF
+
+	   CALL DO_COMMAND(INCMD)
+
+100	   CONTINUE
+
+	   IF (DCL_COMMAND.AND.TRIM(DCL_CMD).EQ.0) CALL EXIT
+
+	END DO
+
+1010	FORMAT(Q,A)
+
+	END
+
+
+
+
+	SUBROUTINE DO_COMMAND(INCMD)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING /.FALSE./
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /NEXT_COMMAND/ NEXT_COMMAND
+	CHARACTER NEXT_COMMAND*64
+
+	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER HELP_DIRECTORY*64,SAVE_FOLDER*44
+
+	CHARACTER*(*) INCMD
+
+	NEXT_COMMAND = ' '
+
+        IER = MINGT0(INDEX(INCMD(:TRIM(INCMD)),' '),INDEX(INCMD,'/'))
+	IF (IER.GT.0) INCMD = '    '//INCMD(IER:)	! Save qualifiers
+	CALL CLI$GET_VALUE('$VERB',INCMD(:4))		! Get user's command.
+
+	IF (HLEN.EQ.0) THEN
+	   IER = LIB$SYS_TRNLOG('BULL_HELP',HLEN,HELP_DIRECTORY)
+	   IF (IER.NE.1) THEN
+	      HELP_DIRECTORY = 'SYS$HELP:'
+	      HLEN = 9
+	   ELSE IF (HELP_DIRECTORY(HLEN:HLEN).NE.':'.AND.
+     &	   	 HELP_DIRECTORY(HLEN:HLEN).NE.']') THEN
+	      HELP_DIRECTORY = HELP_DIRECTORY(:HLEN)//':'
+	      HLEN = HLEN + 1
+	   END IF
+	END IF
+
+	IF (INCMD(:4).EQ.'BACK'.AND.DIR_COUNT.NE.0) THEN
+	   DIR_COUNT = -1
+	   CALL DIRECTORY(DIR_COUNT)
+	   INCMD = ' '
+C	ELSE IF (INCMD(:4).EQ.'BACK'.AND.FOLDER_COUNT.NE.0) THEN
+C	      FOLDER_COUNT = -1
+C	      CALL DIRECTORY_FOLDERS(FOLDER_COUNT)
+C	      INCMD = ' '
+	ELSE
+	   DIR_COUNT = 0			! Reinit display pointers
+	   READ_COUNT = 0
+	   FOLDER_COUNT = 0
+	   INDEX_COUNT = 0
+	END IF
+
+	IF_ADD = INCMD(:3).EQ.'ADD'
+	IF (IF_ADD) IF_ADD = .NOT.CLI$PRESENT('SELECT_FOLDER')
+	IF (READ_ONLY.AND.(IF_ADD.OR.INCMD(:3).EQ.'DEL'.OR.
+     &	    INCMD(:4).EQ.'POST'.OR.
+     &	    INCMD(:3).EQ.'CHA'.OR.INCMD(:3).EQ.'REP')) THEN
+	   					! FOLDER can only be read?
+	   WRITE (6,'('' ERROR: Access to folder limited to reading.'')')
+	ELSE IF (INCMD(:3).EQ.'ADD') THEN	! ADD?
+	   IF (REMOTE_SET.GE.3) THEN
+	      IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+		 WRITE (6,'('' ERROR: /FOLDER not valid when posting'',
+     &			    '' a message to a news group.'')')
+	      ELSE
+		 INCMD = 'POST '//INCMD(4:)
+		 IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+		 CALL RESPOND
+	      END IF
+	   ELSE
+	      CALL ADD
+	   END IF
+	ELSE IF (INCMD(:3).EQ.'ATT') THEN	! ATTACH?
+	   CALL ATTACH
+	ELSE IF (INCMD(:4).EQ.'BACK') THEN	! BACK?
+	   IF (BULL_POINT.LE.1) THEN
+	      WRITE(6,'('' ERROR: There are no more preceding messages.'')')
+	   ELSE
+	      CALL READ_MSG(READ_COUNT,BULL_POINT-1)  ! Try to read previous
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'CHAN') THEN		! CHANGE?
+	   CALL REPLACE				! Replace old bulletin
+	ELSE IF (INCMD(:4).EQ.'COPY') THEN		! COPY?
+	   CALL MOVE(.FALSE.)
+	ELSE IF (INCMD(:4).EQ.'CREA') THEN		! CREATE?
+	   CALL CREATE_FOLDER			! Go create the folder
+	ELSE IF (INCMD(:4).EQ.'CURR') THEN		! CURRENT?
+	   READ_COUNT = -1		! Reread current message from beginning.
+	   CALL READ_MSG(READ_COUNT,BULL_POINT)
+	ELSE IF (INCMD(:4).EQ.'DELE') THEN 	! DELETE?
+	   CALL DELETE_MSG			! Go delete bulletin
+	ELSE IF (INCMD(:4).EQ.'DIRE') THEN		! DIRECTORY?
+	   IF (CLI$PRESENT('FOLDER').AND.CLI$PRESENT('NEWS')) THEN
+	      WRITE (6,'('' ERROR: /NEWS and /FOLDER cannot be ''
+     &		         ''specified at the same time.'')')
+	   ELSE IF (CLI$PRESENT('FOLDER').OR.		! /FOLDER specified?
+     &	       CLI$PRESENT('NEWS')) THEN		! or /NEWS?
+	      CALL DIRECTORY_FOLDERS(FOLDER_COUNT)	! Show all folders
+	   ELSE IF (CLI$PRESENT('SELECT_FOLDER')) THEN! Folder specified?
+	      CALL SELECT_FOLDER(.TRUE.,IER)		! Try to select folder
+	      IF (IER) THEN				! If successful
+		 CALL DIRECTORY(DIR_COUNT)		! Show messages
+	      END IF
+	   ELSE
+	      CALL DIRECTORY(DIR_COUNT)		! Show messages
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'FILE'.OR.
+     &		 INCMD(:4).EQ.'EXTR') THEN		! FILE?
+	   CALL FILE(0,.TRUE.,.FALSE.)			! Copy bulletin to file
+	ELSE IF (INCMD(:4).EQ.'EXCL') THEN		! EXCLUDE?
+	   CALL INCLUDE(.TRUE.)
+	ELSE IF (INCMD(:1).EQ.'E'.OR.
+     &		 INCMD(:4).EQ.'QUIT') THEN		! EXIT?
+	   CALL EXIT				! Exit from program
+	ELSE IF (INCMD(:4).EQ.'FIRS') THEN		! FIRST?
+	   READ_COUNT = -1
+	   BULL_READ = 1
+	   CALL READ_MSG(READ_COUNT,BULL_READ)
+	ELSE IF (INCMD(:4).EQ.'HELP') THEN		! HELP?
+	   CALL HELP(HELP_DIRECTORY(:HLEN)//'BULL.HLB')	! Get help
+	ELSE IF (INCMD(:3).EQ.'IND') THEN		! INDEX?
+	   INDEX_COUNT = 1
+	   CALL FULL_DIR
+	ELSE IF (INCMD(:4).EQ.'INCL'.OR.		! INCLUDE?
+     &	         INCMD(:4).EQ.'THRE') THEN		! THREAD?
+	   CALL INCLUDE(.FALSE.)
+	ELSE IF (INCMD(:4).EQ.'LAST') THEN		! LAST?
+	   READ_COUNT = -1
+	   BULL_READ = 9999999
+	   CALL READ_MSG(READ_COUNT,BULL_READ)
+	ELSE IF (INCMD(:4).EQ.'MARK') THEN		! MARK?
+	   CALL TAG(.TRUE.,1)
+	ELSE IF (INCMD(:4).EQ.'MAIL'.OR.
+     &		 INCMD(:4).EQ.'FORW') THEN		! MAIL?
+	   CALL MAIL
+	ELSE IF (INCMD(:3).EQ.'MOD') THEN		! MODIFY?
+	   CALL MODIFY_FOLDER
+	ELSE IF (INCMD(:4).EQ.'MOVE') THEN		! MOVE?
+	   CALL MOVE(.TRUE.)
+	ELSE IF (INCMD(:4).EQ.'NEWS') THEN		! NEWS
+	   CALL DIRECTORY_FOLDERS(FOLDER_COUNT)	! Show new folders
+	ELSE IF (INCMD(:4).EQ.'NEXT'.OR.INCMD(:1).EQ.'N') THEN    ! NEXT?
+	   CALL READ_MSG(READ_COUNT,BULL_POINT+1)	! Read next bulletin
+	ELSE IF (INCMD(:4).EQ.'POST') THEN		! POST?
+	   IF (BTEST(FOLDER_FLAG,11)) THEN
+	      INCMD = 'ADD '//INCMD(5:)
+	      IER=CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL ADD
+	   ELSE
+	      CALL RESPOND
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'PRIN') THEN		! PRINT?
+	   CALL PRINT(0,.TRUE.)			! Printout bulletin
+	ELSE IF (INCMD(:4).EQ.'READ') THEN		! READ?
+	   IF (CLI$PRESENT('THREADS')) NEXT_COMMAND = 'READ/THREADS'
+	   IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN		! Bulletin specified?
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) BULL_READ	! Yes
+	      READ_COUNT = -1
+	      CALL READ_MSG(READ_COUNT,BULL_READ)
+	   ELSE
+	      CALL READ_MSG(READ_COUNT,BULL_POINT+1)
+	   END IF
+	ELSE IF (INCMD(:3).EQ.'REM') THEN		! REMOVE?
+	   CALL REMOVE_FOLDER
+	ELSE IF (INCMD(:3).EQ.'REP') THEN		! REPLY?
+	   IF (.NOT.BTEST(FOLDER_FLAG,11).AND.(REMOTE_SET.GE.3.OR.
+     &	      INDEX(FOLDER_DESCRIP,'<').GT.0)) THEN
+	      CALL RESPOND
+	   ELSE
+	      CALL REPLY
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'RESP') THEN		! RESPOND?
+	   CALL RESPOND
+	ELSE IF (INCMD(:4).EQ.'RESE') THEN		! RESET?
+	   CALL RESET
+	ELSE IF (INCMD(:3).EQ.'SEA') THEN		! SEARCH?
+	   NEXT_COMMAND = 'SEARCH'
+	   CALL SEARCH(READ_COUNT)
+	ELSE IF (INCMD(:3).EQ.'SEE') THEN		! SEEN?
+	   CALL TAG(.TRUE.,2)
+	ELSE IF (INCMD(:3).EQ.'SEL') THEN		! SELECT?
+	   CALL SELECT_FOLDER(.TRUE.,IER)
+	ELSE IF (INCMD(:3).EQ.'SET') THEN		! SET?
+	   CALL CLI$GET_VALUE('SET_PARAM1',BULL_PARAMETER)
+	   IF (BULL_PARAMETER(:2).EQ.'FO') THEN		! SET FOLDER?
+	      CALL SELECT_FOLDER(.TRUE.,IER)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'FI') THEN	! SET FILE_DIRECTORY?
+	      CALL SET_CUSTOM('file_directory')
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'PRI') THEN		! SET PRIVS?
+	      CALL SET_PRIV
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'PA') THEN		! SET PAGE?
+	      PAGING = .TRUE.
+	      WRITE (6,'('' PAGE has been set.'')')
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'K') THEN		! SET KEYPAD?
+	      CALL SET_KEYPAD
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOK') THEN		! SET NOKEYPAD?
+	      CALL SET_NOKEYPAD
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPA') THEN	! SET NOPAGE?
+	      PAGING = .FALSE.
+	      WRITE (6,'('' NOPAGE has been set.'')')
+	   ELSE IF (FOLDER_NUMBER.EQ.-1.AND.REMOTE_SET.EQ.1) THEN
+	      WRITE (6,'('' ERROR: Invalid command for remote folder.'')')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'SY') THEN		! SET SYSTEM?
+	      CALL SET_SYSTEM(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOSY') THEN	! SET NOSYSTEM?
+	      CALL SET_SYSTEM(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'BB') THEN		! SET BBOARD?
+	      CALL SET_BBOARD(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOBB') THEN	! SET NOBBOARD?
+	      CALL SET_BBOARD(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'DU') THEN		! SET DUMP?
+	      CALL SET_FOLDER_FLAG(.TRUE.,1,'DUMP')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODU') THEN	! SET NODUMP?
+	      CALL SET_FOLDER_FLAG(.FALSE.,1,'DUMP')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'ST') THEN		! SET STRIP?
+	      CALL SET_FOLDER_FLAG(.TRUE.,4,'STRIP')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOST') THEN	! SET NOSTRIP?
+	      CALL SET_FOLDER_FLAG(.FALSE.,4,'STRIP')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'DI') THEN		! SET DIGEST?
+	      CALL SET_FOLDER_FLAG(.TRUE.,5,'DIGEST')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODI') THEN	! SET NODIGEST?
+	      CALL SET_FOLDER_FLAG(.FALSE.,5,'DIGEST')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'AL') THEN		! SET ALWAYS?
+	      CALL SET_FOLDER_FLAG(.TRUE.,7,'ALWAYS')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAL') THEN	! SET NOALWAYS?
+	      CALL SET_FOLDER_FLAG(.FALSE.,7,'ALWAYS')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'AN') THEN	     ! SET ANONYMOUS?
+	      CALL SET_FOLDER_FLAG(.TRUE.,14,'ANONYMOUS')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAN') THEN     ! SET NOANONYMOUS?
+	      CALL SET_FOLDER_FLAG(.FALSE.,14,'ANONYMOUS')
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'COM') THEN	    ! SET COMPRESS?
+	      CALL SET_FOLDER_FLAG(.TRUE.,12,'COMPRESS')
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOCOM') THEN   ! SET NOCOMPRESS?
+	      CALL SET_FOLDER_FLAG(.FALSE.,12,'COMPRESS')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'PO') THEN	    ! SET POST_ONLY?
+	      CALL SET_FOLDER_FLAG(.TRUE.,10,'POST_ONLY')
+	      IF (BTEST(FOLDER_FLAG,11)) THEN
+		 CALL SET_FOLDER_FLAG(.FALSE.,11,'ADD_ONLY')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPO') THEN    ! SET NOPOST_ONLY?
+	      CALL SET_FOLDER_FLAG(.FALSE.,10,'POST_ONLY')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'AD') THEN	    ! SET ADD_ONLY?
+	      CALL SET_FOLDER_FLAG(.TRUE.,11,'ADD_ONLY')
+	      IF (BTEST(FOLDER_FLAG,10)) THEN
+		 CALL SET_FOLDER_FLAG(.FALSE.,10,'POST_ONLY')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAD') THEN    ! SET NOADD_ONLY?
+	      CALL SET_FOLDER_FLAG(.FALSE.,11,'ADD_ONLY')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOTI') THEN	! SET NOTIFY?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(1,-1,-1)
+	      ELSE
+		 CALL SET_USER_FLAG(1,-1,-1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXP') THEN		! SET EXPIRE?
+	      IER = CLI$GET_VALUE('EXPIRATION',BULL_PARAMETER,LEN_P)
+	      IF (LEN_P.LE.3) THEN
+		 READ (BULL_PARAMETER,'(I<LEN_P>)') LIMIT
+		 CALL SET_FOLDER_EXPIRE_LIMIT(LIMIT)
+	      ELSE
+		 WRITE (6,'('' ERROR: Invalid expiration specified.'')')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODE') THEN	! SET NODE?
+	      CALL SET_NODE(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:6).EQ.'NONODE') THEN	! SET NONODE?
+	      CALL SET_NODE(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOEXP') THEN	! SET NOEXPIRE?
+	      CALL SET_FOLDER_EXPIRE_LIMIT(0)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NONOT') THEN	! SET NONOTIFY?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(0,-1,-1)
+	      ELSE
+		 CALL SET_USER_FLAG(0,-1,-1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'SH') THEN		! SET SHOWNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,1)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOS') THEN	! SET NOSHOWNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'R') THEN		! SET READNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,1,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,1,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOR') THEN	! SET NOREADNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'BR') THEN		! SET BRIEF?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,1,1)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,1,1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOBR') THEN	! SET NOBRIEF?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'SU') THEN	! SET SUBSCRIBE?
+	      IF (REMOTE_SET.GE.3) THEN
+		 D1 = 0
+		 D2 = 0
+		 D3 = 0
+		 CALL SET_FOLDER_DEFAULT(D1,D2,D3)
+	      ELSE
+		 WRITE (6,'('' ERROR: Command invalid for folder.'')')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'A') THEN	! SET ACCESS?
+	      CALL SET_ACCESS(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOA') THEN	! SET NOACCESS?
+	      CALL SET_ACCESS(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'C') THEN	! SET CONTINUOUS_BRIEF
+	      CALL SET_BRIEF_CONTINUOUS(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOC') THEN	! SET NOCONTINUOUS_BRIEF
+	      CALL SET_BRIEF_CONTINUOUS(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'GEN') THEN	! SET GENERIC?
+	      CALL SET_GENERIC(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOGEN') THEN	! SET NOGENERIC?
+	      CALL SET_GENERIC(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'LIB') THEN	! SET LIBRARY?
+	      CALL SET_LIBRARY
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'LOG') THEN		! SET LOGIN?
+	      CALL SET_LOGIN(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOLOG') THEN	! SET NOLOGIN?
+	      CALL SET_LOGIN(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'PRO') THEN	 ! SET PROMPT_EXPIRE?
+	      CALL SET_FOLDER_FLAG(.FALSE.,3,'PROMPT_EXPIRE')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPR') THEN ! SET NOPROMPT_EXPIRE?
+	      CALL SET_FOLDER_FLAG(.TRUE.,3,'PROMPT_EXPIRE')
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'DEF') THEN	! SET DEFAULT_EXPIRE?
+	      CALL SET_DEFAULT_EXPIRE
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'NE') THEN	! SET NEWS?
+	      CALL SET_NEWS
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXC') THEN	! SET EXCLUDE?
+	      BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,4)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOEXC') THEN ! SET NOEXCLUDE?
+	      BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,4)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXL') THEN	! SET EXLIMIT?
+	      CALL SET_CUSTOM('exclude_limit')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NAME') THEN  ! SET NAME?
+	      CALL SET_NEWNAME
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'GAT') THEN	    ! SET GATEWAY?
+	      CALL SET_FOLDER_FLAG(.TRUE.,15,'GATEWAY')
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOGAT') THEN   ! SET NOGATEWAY?
+	      CALL SET_FOLDER_FLAG(.FALSE.,15,'GATEWAY')
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'SHOW') THEN		! SHOW?
+	   CALL CLI$GET_VALUE('SHOW_PARAM1',BULL_PARAMETER,LEN_P)
+	   IF (BULL_PARAMETER(:2).EQ.'EX') THEN		! SHOW EXCLUDE?
+	      CALL SHOW_EXCLUDE(0)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'FL') THEN	! SHOW FLAGS?
+	      CALL SHOW_FLAGS
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'FO') THEN	! SHOW FOLDER?
+	      CALL SHOW_FOLDER
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'IN'.OR.
+     &		    BULL_PARAMETER(:2).EQ.'TH') THEN	! SHOW INCLUDE?
+	      CALL SHOW_EXCLUDE(1)
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'K') THEN	! SHOW KEYPAD
+	      CALL SHOW_KEYPAD(HELP_DIRECTORY(:HLEN)//'BULL.HLB')
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'L') THEN	! SHOW LIBRARY
+	      CALL SHOW_LIBRARY
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'N') THEN	! SHOW NEW?
+	      SAVE_FOLDER_NUMBER = FOLDER_NUMBER
+	      SAVE_FOLDER = FOLDER
+	      CALL NEW_MESSAGE_NOTIFICATION
+	      FOLDER1 = SAVE_FOLDER
+	      FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'P') THEN	! SHOW PRIVILEGES?
+	      CALL SHOW_PRIV
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'U') THEN	! SHOW USER?
+	      CALL SHOW_USER
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'V') THEN	! SHOW VERSION?
+	      CALL SHOW_VERSION
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'SPAW') THEN           ! SPAWN command?
+	   CALL SPAWN_PROCESS
+	ELSE IF (INCMD(:3).EQ.'SUB') THEN            ! SUBSCRIBE command?
+	   CALL SUBSCRIBE
+	ELSE IF (INCMD(:4).EQ.'UNDE') THEN		! UNDELETE?
+	   CALL UNDELETE
+	ELSE IF (INCMD(:3).EQ.'UNM') THEN		! UNMARK?
+	   CALL TAG(.FALSE.,1)
+	ELSE IF (INCMD(:4).EQ.'UNSE') THEN		! UNSEEN?
+	   CALL TAG(.FALSE.,2)
+	ELSE IF (INCMD(:4).EQ.'UNSU') THEN           ! UNSUBSCRIBE command?
+	   CALL UNSUBSCRIBE
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE COMMAND_INPUT(IER)
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
+	CHARACTER*44 PROMPT
+
+	CALL GET_INPUT_PROMPT(INCMD,IER,PROMPT(:LPROMPT))
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE ADD
+C
+C  SUBROUTINE ADD
+C
+C  FUNCTION: Adds bulletin to bulletin file.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /INDESCRIP/ INDESCRIP
+	CHARACTER*(INPUT_LENGTH) INDESCRIP
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER INEXDATE*12,INEXTIME*12,INDENT*4
+
+	CHARACTER INLINE*80,OLD_FOLDER*44,LOCAL_NODE*8
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED,BULLETIN_SUBCOMMANDS
+
+	EDITIT = (CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.
+     &           (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))
+
+	IF (CLI$PRESENT('EXTRACT').AND..NOT.EDITIT) THEN
+	   WRITE (6,'('' ERROR: Cannot extract text without /EDIT.'')')
+	   RETURN
+	END IF
+
+	IF (EDITIT.AND..NOT.CLI$PRESENT('EXTRACT')
+     &	    .AND..NOT.CLI$PRESENT('FILESPEC')) THEN
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	END IF
+
+	CALL DISABLE_CTRL		! Disable CTRL-Y & -C
+
+	ALLOW = SETPRV_PRIV()
+
+	OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	OLD_FOLDER = FOLDER
+
+	LEN_P = 0
+
+	IF (CLI$PRESENT('EXTRACT')) THEN
+	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	   LEN_P = TRIM(BULL_PARAMETER)
+	   OPEN(UNIT=3,FILE=BULL_PARAMETER(:LEN_P),IOSTAT=IER,
+     &		RECL=LINE_LENGTH,
+     &		STATUS='NEW',CARRIAGECONTROL='LIST',FORM='FORMATTED')
+
+	   IF (IER.NE.0) THEN
+	      CALL ERRSNS(IDUMMY,IER)
+	      CALL SYS_GETMSG(IER)
+	      GO TO 910
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+
+	   LENI = 0
+	   IF (CLI$PRESENT('INDENT').NE.%LOC(CLI$_NEGATED)) THEN
+	      CALL CLI$GET_VALUE('INDENT',INDENT,LENI)
+	   END IF
+	   DO WHILE (ILEN.GT.0)			! Copy bulletin into file
+	      IF (LENI.EQ.0) THEN
+	         WRITE (3,'(A)') INPUT(:ILEN)
+	      ELSE
+	         WRITE (3,'(A)') INDENT(:LENI)//INPUT(:ILEN)
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END DO
+
+90	   CALL CLOSE_BULLFIL
+	END IF
+
+	SELECT_FOLDERS = .FALSE.
+	IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	   CALL GET_FOLDER_INFO(IER)
+	   IF (.NOT.IER) GO TO 910
+	   SELECT_FOLDERS = .TRUE.
+	ELSE
+	   NODE_NUM = 1
+	   NODES(1) = OLD_FOLDER
+	END IF
+
+	IF (CLI$PRESENT('FILESPEC')) THEN
+	   IER = CLI$GET_VALUE('FILESPEC',BULL_PARAMETER,LEN_P)
+	   CALL DISABLE_PRIVS
+	   IF (.NOT.CLI$PRESENT('EXTRACT')) THEN
+	      OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
+	   ELSE
+	      OPEN (UNIT=4,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
+	      IER = 0
+	      ICOUNT = 0
+	      DO WHILE (IER.EQ.0)
+		 READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		 IF (IER.EQ.0) THEN
+		    IF (ICOUNT.EQ.0) WRITE (3,'(A)') ' '
+		    ICOUNT = ICOUNT + 1
+		    WRITE (3,'(A)') INPUT(:ILEN)
+		 END IF
+	      END DO
+	      CLOSE (UNIT=4)
+	      BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	      LEN_P = TRIM(BULL_PARAMETER)
+	   END IF
+	   CALL ENABLE_PRIVS	! Reset SYSPRV privileges
+	END IF
+
+	IF (FOLDER_NUMBER.GT.0.AND.		! If folder set and
+     &	    CLI$PRESENT('NODES')) THEN		! Decnet nodes specified?
+	   WRITE (6,'('' ERROR: /NODES cannot be used with folder set.'')')
+	   GO TO 910
+	END IF
+
+	IF (.NOT.BTEST(FOLDER_FLAG,2).AND.FOLDER_NUMBER.NE.0.AND.
+     &	   (CLI$PRESENT('SYSTEM').OR.		! Is /SYSTEM switch present?
+     &	    CLI$PRESENT('BROADCAST').OR.	! Is /BROADCAST swtich present?
+     &	    CLI$PRESENT('SHUTDOWN'))) THEN	! Is /SHUTDOWN switch present?
+	   WRITE (6,'('' ERROR: Folder is not a SYSTEM folder.'')')
+	   GO TO 910
+	END IF
+
+	IF (CLI$PRESENT('SYSTEM')) THEN		! Is /SYSTEM switch present?
+	   IF (.NOT.ALLOW) THEN			! If no privileges
+	      WRITE(ERROR_UNIT,1070)		! Tell user
+	      GO TO 910				! and abort
+	   END IF
+	   SYSTEM = 1				! Set system bit
+	ELSE
+	   SYSTEM = 0				! Clear system bit
+	END IF
+
+	IF (CLI$PRESENT('BROADCAST')) THEN	! Is /BROADCAST switch present?
+	   IF (.NOT.(ALLOW.OR.OPER_PRIV())) THEN	! If no privileges
+	      WRITE(ERROR_UNIT,1080)		! Tell user
+	      GO TO 910				! and abort
+	   ELSE IF (CLI$PRESENT('CLUSTER')) THEN
+	      SYSTEM = SYSTEM.OR.8
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('PERMANENT')) THEN	! Is /PERMANENT switch present?
+	   IF (F_EXPIRE_LIMIT.GT.0.AND..NOT. ! Expiration limit present
+     &		FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	      WRITE(ERROR_UNIT,1083)
+	      GO TO 910
+	   ELSE
+	      SYSTEM = SYSTEM.OR.2		! Set permanent bit
+	      INEXDATE = '5-NOV-2100'
+	      INEXTIME = '00:00:00.00'
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SHUTDOWN')) THEN	! Is /SHUTDOWN switch present?
+	   IF (.NOT.ALLOW) THEN			! If no privileges
+	      WRITE(ERROR_UNIT,1082)		! Tell user
+	      GO TO 910				! and abort
+	   ELSE
+	      IER = CLI$GET_VALUE('SHUTDOWN',INLINE)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+		 IF (REMOTE_SET) THEN		! Can't specify node name if
+		    WRITE (6,1090)		! remote folder, as no code
+		    GO TO 910			! present to send the name.
+		 END IF
+	         CALL GET_NODE_NUMBER_OTHER(NODE_NUMBER,NODE_AREA,INLINE)
+		 IF (NODE_AREA.EQ.0) GO TO 910	! Invalid node name
+	      ELSE
+	         CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	      END IF
+	      SYSTEM = SYSTEM.OR.4		! Set shutdown bit
+	      INEXDATE = '5-NOV-2100'
+              WRITE (INEXTIME(1:),'(I2)') NODE_NUMBER/60
+              WRITE (INEXTIME(3:),'(I2)') MOD(NODE_NUMBER,60)
+              WRITE (INEXTIME(7:),'(I2)') NODE_AREA/60
+              WRITE (INEXTIME(9:),'(I2)') MOD(NODE_AREA,60)
+	      DO I=1,11
+		 IF (INEXTIME(I:I).EQ.' ') INEXTIME(I:I) = '0'
+	      END DO
+	      INEXTIME = INEXTIME(1:2)//':'//INEXTIME(3:4)//':'//
+     &			 INEXTIME(7:8)//'.'//INEXTIME(9:10)
+	   END IF
+	END IF
+
+	SELECT_NODES = .FALSE.
+	IF (CLI$PRESENT('NODES')) THEN
+	   CALL GET_NODE_INFO
+	   IF (NODE_ERROR) GO TO 940
+	   SELECT_NODES = .TRUE.
+	END IF
+
+	IF ((SYSTEM.AND.7).LE.1.AND.(CLI$PRESENT('SELECT_FOLDER').OR.
+     &	    CLI$PRESENT('NODES').OR..NOT.BTEST(FOLDER_FLAG,10))) THEN
+	   CALL GET_EXPIRED(INPUT,IER)          ! Not permanent or shutdown 
+	   IF (.NOT.IER) GO TO 910
+	   INEXDATE = INPUT(:11)
+	   INEXTIME = INPUT(13:23)
+	END IF
+
+	IF (INCMD(:3).EQ.'REP') THEN		! REPLY?
+	   LENDES = TRIM(INDESCRIP)		! filled in by main subroutine
+	ELSE IF (CLI$PRESENT('SUBJECT')) THEN	! /SUBJECT specified
+	   CALL CLI$GET_VALUE('SUBJECT',INDESCRIP,LENDES)
+	ELSE
+	   WRITE(6,1050)			! Request header for bulletin
+	   CALL GET_LINE(INDESCRIP,LENDES)	! Get input line
+	   IF (LENDES.LE.0) GO TO 910
+	END IF
+
+	LENDES = MIN(LEN(INDESCRIP)-6,LENDES)	! Make room for "Subj: "
+
+C
+C  If file specified in ADD command, read file to obtain bulletin.
+C  Else, read the bulletin from the terminal.
+C
+
+	IF (EDITIT.AND..NOT.DECNET_PROC) THEN	! If /EDIT specified
+	   IF (LEN_P.EQ.0) THEN			! If no file param specified
+	      CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 ERR=910,FORM='FORMATTED')
+	      LEN_P = 1
+	   ELSE
+	      CLOSE (UNIT=3)
+	      CALL MAILEDIT(BULL_PARAMETER(:LEN_P),'SYS$LOGIN:BULL.SCR')
+	      IF (CLI$PRESENT('EXTRACT')) THEN
+	         CONTEXT = 0
+	         CALL LIB$FIND_FILE('SYS$LOGIN:BULL.SCR',INPUT,CONTEXT)
+	         VERSION = INDEX(INPUT,';') + 1
+	         IF (INPUT(VERSION:VERSION).EQ.'1') THEN
+	            CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	         END IF
+	      END IF
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 ERR=910,FORM='FORMATTED')
+	   END IF
+	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	   LEN_P = TRIM(BULL_PARAMETER)
+	END IF
+
+	ICOUNT = 0				! Line count for bulletin
+
+	END = 0
+	BLENGTH = 35
+	IF (CLI$PRESENT('BELL')) BLENGTH = 37
+	IF (LEN_P.GT.0) THEN			! If file param in ADD command
+	   DO WHILE(1)				! Read until end of file to
+	      READ (3,'(Q,A)',END=10) ILEN,INPUT! get record count
+	      IF (ILEN.GT.LINE_LENGTH) GO TO 950
+	      ICOUNT = ICOUNT + 1 + MIN(ILEN,80)
+	      BLENGTH = BLENGTH + ILEN - 1 + 2
+	      IF (ILEN.EQ.0) ICOUNT = ICOUNT + 1! COPY_BULL writes line with
+	   END DO				! 1 space for blank line
+	ELSE					! If no input file
+	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	   LEN_P = TRIM(BULL_PARAMETER)
+	   OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',
+     &		STATUS='NEW',
+     &		FORM='FORMATTED',RECL=LINE_LENGTH) ! Temp file to save message
+	   WRITE (6,1000)			! Request input from terminal
+	   ILEN = LINE_LENGTH + 1		! Length of input line
+	   ICOUNT = 0				! Character count counter
+	   DO WHILE (ILEN.GE.0)			! Input until no more input
+	      CALL GET_LINE(INPUT,ILEN)		! Get input line
+	      IF (ILEN.GT.LINE_LENGTH) THEN	! Input line too long
+		 WRITE(6,'('' ERROR: Input line length > '',I,
+     &			''.  Reinput:'')') LINE_LENGTH
+	      ELSE IF (ILEN.GE.0) THEN		! If good input line entered
+		 ICOUNT = ICOUNT + ILEN		! Update counter
+	         BLENGTH = BLENGTH + ILEN - 1 + 2
+		 WRITE(3,2010) INPUT(:ILEN)	! Save line in scratch file
+	      END IF
+	   END DO
+	   IF (ILEN.EQ.-1) GO TO 910		! CTRL_C entered, error out
+10	   IF (ICOUNT.EQ.0) GO TO 910		! No lines entered, error out
+	ENDIF
+
+	REWIND (UNIT=3)
+
+	BRDCST = .FALSE.
+
+	IF (CLI$PRESENT('BROADCAST').AND.BLENGTH.GT.82*12+2) THEN
+	   WRITE (6,'('' Message is too long for broadcasting by '',
+     &	        I6,'' characters.  Limit is '',I3,''.'')')
+     &			BLENGTH - 82*12 - 2, 82*12 - 2
+	   CALL GET_INPUT_PROMPT(INPUT,ILEN,
+     &		'Type C to broadcast anyway, A to only ADD message,'
+     &   	//' or Q to Quit: ')
+	   IF (STREQ(INPUT(:1),'Q')) THEN
+	      GO TO 910
+	   ELSE IF (STREQ(INPUT(:1),'A')) THEN
+	      BRDCST = .TRUE.
+	   ELSE IF (.NOT.STREQ(INPUT(:1),'C')) THEN
+	      GO TO 910
+	   END IF
+	END IF
+
+	IF (SELECT_NODES.AND.NODE_NUM.GT.0) THEN
+	   INLINE = 'ADD'
+	   IF (CLI$PRESENT('SYSTEM'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/SYSTEM'
+	   IF (CLI$PRESENT('BROADCAST').AND..NOT.BRDCST)
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/BROADCAST'
+	   IF (CLI$PRESENT('PERMANENT'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/PERMANENT'
+	   IF (CLI$PRESENT('SHUTDOWN'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/SHUTDOWN'
+	   IF (CLI$PRESENT('BELL'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/BELL'
+
+	   LEN_INLINE = STR$POSITION(INLINE,' ') - 1
+
+	   DO POINT_NODE=1,NODE_NUM	   	! Write out command to nodes
+	      INLINE = INLINE(:LEN_INLINE)
+
+	      WRITE (POINT_NODE+9,'(A)',ERR=940) INLINE
+	      IF ((SYSTEM.AND.7).LE.1)
+				! If not permanent or shutdown specify date
+     &		WRITE (POINT_NODE+9,'(A)',ERR=940) INEXDATE//' '//INEXTIME
+	      WRITE (POINT_NODE+9,'(A)',ERR=940) INDESCRIP(:LENDES)
+	      IER = 0
+	      DO WHILE (IER.EQ.0)
+	         READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		 ILEN = MIN(ILEN,LINE_LENGTH)
+		 IF (IER.EQ.0) THEN
+		    WRITE (POINT_NODE+9,'(A)',ERR=940) INPUT(:ILEN)
+		 END IF
+	      END DO
+	      WRITE (POINT_NODE+9,'(A)',ERR=940) CHAR(26)
+	      READ (POINT_NODE+9,'(A)',ERR=940,END=940) INPUT
+	      IF (INPUT.EQ.'END') THEN
+	         WRITE (6,'('' Message successfully sent to node '',A)')
+     &				NODES(POINT_NODE)
+	      ELSE
+	         WRITE (6,'('' Error while sending message to node '',A)')
+     &				NODES(POINT_NODE)
+		 WRITE (6,'(A)') INPUT(:80)
+		 GO TO 940
+	      END IF
+	      REWIND (UNIT=3)
+	   END DO
+	END IF
+	
+	IF (SELECT_NODES.AND..NOT.LOCAL_NODE_FOUND) GO TO 95
+					! Exit if local node not specified.
+
+	IF (.NOT.SELECT_FOLDERS) THEN
+	   NODE_NUM = 1				! No folders specified so just
+	   NODES(1) = FOLDER			! add to select folder
+	END IF
+
+	IER = SYS_TRNLNM('SYS$NODE',LOCAL_NODE)
+	LNODE = TRIM(LOCAL_NODE)	
+
+C
+C  Add bulletin to bulletin file and directory entry for to directory file.
+C
+
+	DO I = 1,NODE_NUM
+
+	   IF (FOLDER.NE.NODES(I)) THEN
+	      FOLDER_NUMBER = -1
+	      FOLDER1 = NODES(I)
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	   ELSE
+	      IER = 1
+	   END IF
+	   
+	   IF (IER.AND..NOT.BTEST(FOLDER_FLAG,10)) THEN
+	      CALL OPEN_BULLDIR			! Prepare to add dir entry
+
+	      DESCRIP=INDESCRIP(:LENDES)	! Description header
+	      EXDATE=INEXDATE			! Expiration date
+	      EXTIME=INEXTIME
+	      IF (BTEST(FOLDER_FLAG,14)) THEN
+	         FROM = 'ANONYMOUS'
+              ELSE
+	         FROM = USERNAME		! Username
+	      END IF
+
+	      CALL OPEN_BULLFIL			! Prepare to add bulletin
+
+	      CALL READDIR(0,IER1)		! Get NBLOCK
+	      IF (IER1.EQ.0) NBLOCK = 0		! If new file, NBLOCK is 0
+
+	      REWIND (UNIT=3)
+	      OBLOCK = NBLOCK+1
+	      IF (.NOT.BTEST(FOLDER_FLAG,14)) THEN
+	         CALL STORE_BULL(LNODE+TRIM(FROM)+6,'From: '//
+     &		    LOCAL_NODE(:LNODE)//FROM(:TRIM(FROM)),OBLOCK)
+	      END IF
+	      IF (LENDES.GT.LEN(DESCRIP)) THEN
+	         CALL STORE_BULL(LENDES+6,
+     &			'Subj: '//INDESCRIP(:LENDES),OBLOCK)
+	      END IF
+	      CALL COPY_BULL(3,1,OBLOCK,IER1)	! Add the new bulletin
+	      IF (IER1.NE.0) GO TO 930		! Error in creating bulletin
+	      LENGTH = OCOUNT - (NBLOCK+1) + 1
+
+	      IF (.NOT.BRDCST.AND.CLI$PRESENT('BROADCAST').AND.
+     &		 (.NOT.REMOTE_SET.OR.FOLDER_NUMBER.GT.0)) THEN
+		 CALL GET_BROADCAST_MESSAGE(CLI$PRESENT('BELL'))
+	      END IF
+
+	      CALL ADD_ENTRY			! Add the new directory entry
+
+	      CALL CLOSE_BULLFIL		! Finished adding bulletin
+
+	      IF (FOLDER_NUMBER.GE.0) THEN
+	         DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &			       F_NEWEST_BTIM)
+	         CALL UPDATE_FOLDER		! Update info in folder file
+C
+C  If user is adding message, an no new messages, update last read time for
+C  folder, so user is not alerted of new message which is owned by user.
+C
+	         IF (DIFF.GE.0) THEN
+	            LAST_READ_BTIM(1,FOLDER_NUMBER+1) = F_NEWEST_BTIM(1)
+	            LAST_READ_BTIM(2,FOLDER_NUMBER+1) = F_NEWEST_BTIM(2)
+	         END IF
+		 IF (BULL_TAG.AND.BTEST(BULL_TAG,1)) THEN
+		    CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+		    CALL ADD_TAG(IER1,2)
+		 END IF
+	      END IF
+
+	      CALL CLOSE_BULLDIR		! Totally finished with add
+C
+C  Broadcast the bulletin if requested.
+C
+	      IF (.NOT.BRDCST.AND.CLI$PRESENT('BROADCAST').AND.
+     &		 (.NOT.REMOTE_SET.OR.FOLDER_NUMBER.GT.0)) THEN
+		 BRDCST = .TRUE.
+	         IF (.NOT.CLI$PRESENT('LOCAL')) THEN
+	            CALL BROADCAST_ALL_NODES(CLI$PRESENT('ALL'),
+     &			CLI$PRESENT('CLUSTER'))
+		 END IF
+C
+C  If the folder is remote, and local node is not the node which BULLCP is
+C  on, don't broadcast, as it will be broadcasted by BULLCP.  The remote
+C  node will distribute the broadcast to nodes that are running BULLCP,
+C  but not if the node that originated the message matches.  However, it
+C  has no way of knowing that the originating node is in the same cluster
+C  as that of the BULLCP node.
+C
+		 IF ((REMOTE_SET.AND.LOCAL_NODE(:LNODE-2).EQ.NODENAME)
+     &		     .OR.CLI$PRESENT('LOCAL').OR..NOT.REMOTE_SET)
+     &	            CALL BROADCAST(
+     &			CLI$PRESENT('ALL'),CLI$PRESENT('CLUSTER'))
+	      END IF
+	   ELSE IF (.NOT.IER) THEN
+	      WRITE (6,'('' ERROR: Unable to add message to '',A)')
+     &				NODES(I)
+	   END IF
+           IF (IER.AND.(BTEST(FOLDER_FLAG,10).OR.
+     &			BTEST(FOLDER_FLAG,11)).AND.REMOTE_SET.LT.3) THEN
+	      IF (NEWS_FEED()) THEN
+	         SLIST = INDEX(FOLDER_DESCRIP,'[')
+	      ELSE
+	         SLIST = INDEX(FOLDER_DESCRIP,'<')
+	      END IF
+	      IF (SLIST.GT.0) THEN
+	         INPUT = FOLDER_DESCRIP(SLIST+1:)
+	         IF (NEWS_FEED()) THEN
+	            ILEN = INDEX(INPUT,']') - 1
+	         ELSE
+	            ILEN = INDEX(INPUT,'>') - 1
+	         END IF
+	         IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+	         INPUT = INPUT(:ILEN)
+                 CALL ADD_PROTOCOL(INPUT,ILEN)
+	         CLOSE (UNIT=3,STATUS='SAVE')
+		 IF (BTEST(FOLDER_FLAG,10).OR.BTEST(FOLDER_FLAG,15)) THEN
+	            CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
+     &		       INDESCRIP(:LENDES),STATUS)
+		 ELSE
+	            CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
+     &	   	       FOLDER(:TRIM(FOLDER))//' folder message: '//
+     &		       INDESCRIP(:LENDES),STATUS)
+		 END IF
+	         IF (BULL_PARAMETER.EQ.'SYS$LOGIN:BULL.SCR') THEN
+	            OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		       ERR=910,FORM='FORMATTED')
+	         ELSE
+	            OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		       READONLY,SHARED,ERR=910,FORM='FORMATTED')
+	         END IF
+	      END IF
+	   END IF
+	END DO
+
+95	CLOSE (UNIT=3)			! Close the input file
+	IF (DECNET_PROC) WRITE(5,'(''END'')') ! DECNET operation worked
+
+	LENFRO = 0
+	DO WHILE (CLI$GET_VALUE('CC',INLINE,ILEN).NE.%LOC(CLI$_ABSENT))
+	   CALL ADD_PROTOCOL(INLINE,ILEN)
+	   IF (LENFRO.EQ.0) THEN
+	      INPUT = INLINE(:ILEN)//','
+	   ELSE
+	      INPUT = INPUT(:LENFRO)//INLINE(:ILEN)//','
+	   END IF
+	   LENFRO = LENFRO + ILEN + 1
+	END DO
+
+	IF (LENFRO.GT.1) THEN 
+	   LENFRO = LENFRO - 1
+	   I = 1		! Must change all " to "" in FROM field
+	   DO WHILE (I.LE.LENFRO)
+	      IF (INPUT(I:I).EQ.'"') THEN
+	         INPUT = INPUT(:I)//'"'//INPUT(I+1:)
+	         I = I + 1
+		 LENFRO = LENFRO + 1
+	      END IF
+	      I = I + 1
+	   END DO
+	   CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
+     &			     INDESCRIP(:LENDES),STATUS)
+	END IF
+
+100	CALL ENABLE_CTRL		! Enable CTRL-Y & -C
+	DO I=10,NODE_NUM+9
+	   CLOSE (UNIT=I)
+	END DO
+
+	IF (NEWS_FEED()) THEN
+	   SLIST = INDEX(FOLDER_DESCRIP,'<')
+	   FOLDER1_DESCRIP = 
+     &		FOLDER_DESCRIP(SLIST+1:INDEX(FOLDER_DESCRIP,'>')-1)
+	   CALL NEWS_POST(BULL_PARAMETER(:LEN_P),.FALSE.,IER,
+     &		INDESCRIP)
+	END IF
+
+200	IF (FOLDER_NUMBER.NE.OLD_FOLDER_NUMBER) THEN
+	   FOLDER_NUMBER = OLD_FOLDER_NUMBER
+	   FOLDER1 = OLD_FOLDER
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	END IF
+
+	CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+
+	RETURN
+
+910	WRITE(ERROR_UNIT,1010)
+	CLOSE (UNIT=3,ERR=100)
+	GO TO 200
+
+920	WRITE(ERROR_UNIT,1020)
+	CALL ENABLE_PRIVS
+	GO TO 200
+
+930	WRITE (ERROR_UNIT,1025)
+	CALL CLOSE_BULLFIL
+	CALL CLOSE_BULLDIR
+	CLOSE (UNIT=3)
+	GO TO 200
+
+940	WRITE (6,1015) NODES(POINT_NODE)
+	WRITE (6,1018)
+	CLOSE (UNIT=3)
+	GO TO 200
+
+950	WRITE (6,1030) LINE_LENGTH
+	CLOSE (UNIT=3)
+	GO TO 200
+
+1000	FORMAT (' Enter message: End with ctrl-z, cancel with ctrl-c')
+1010	FORMAT (' No message was added.')
+1015	FORMAT (' ERROR: Unable to reach node ',A)
+1018	FORMAT (' Try using /FOLDER instead of /NODE.')
+1020	FORMAT (' ERROR: Unable to open specified file.')
+1025	FORMAT (' ERROR: Unable to add message to file.')
+1030	FORMAT (' ERROR: Line length in file exceeds ',I,' characters.')
+1050	FORMAT (' Enter description header.')
+1070	FORMAT (' ERROR: SETPRV privileges are needed for system
+     & messages.')
+1080	FORMAT (' ERROR: SETPRV privileges are needed to broadcast
+     & messages.')
+1082	FORMAT (' ERROR: SETPRV privileges are needed to shutdown
+     & messages.')
+1083	FORMAT (' ERROR: Folder has expiration limit.')
+1090	FORMAT (' ERROR: Nodename cannot be specified for shutdown
+     & if folder is remote.')
+2010	FORMAT(A)
+2020	FORMAT(1X,A)
+
+	END
+
+
+	SUBROUTINE SUBTIME(BTIM,DAYS_BEFORE_TODAY,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER DAYS_BEFORE_TODAY*(*),TODAY_DATE*24
+
+	INTEGER BTIM(2),TODAY_BTIM(2)
+
+	IER = SYS$BINTIM(DAYS_BEFORE_TODAY,BTIM)
+	IF (.NOT.IER) RETURN
+
+	BTIM(1) = -BTIM(1)		! Convert to negative delta time
+	BTIM(2) = -BTIM(2)-1
+
+	IER = SYS$ASCTIM(TLEN,TODAY_DATE,,)
+	CALL SYS$BINTIM(TODAY_DATE(:TLEN),TODAY_BTIM)
+
+	CALL LIB$SUBX(TODAY_BTIM,BTIM,BTIM)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE BROADCAST_ALL_NODES(ALL,CLUSTER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	PARAMETER BRDCST_LIMIT = 82*12 + 2 + 2
+	CHARACTER*(BRDCST_LIMIT) BMESSAGE
+
+	COMMON /BROAD_MESSAGE/ BMESSAGE,BLENGTH
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER RESPONSE*4
+
+	IF (.NOT.TEST_BULLCP().OR.REMOTE_SET) RETURN
+
+	CALL OPEN_BULLUSER_SHARED
+
+	REMOTE_FOUND = .FALSE.
+	TEMP_USER = ':'
+
+	DO WHILE (.NOT.REMOTE_FOUND)
+	   DO WHILE (REC_LOCK(IER))		 
+	      READ (4,KEYGT=TEMP_USER,IOSTAT=IER)
+     &		TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG
+	   END DO
+	   IF (TEMP_USER(:1).NE.':') THEN
+	      CALL CLOSE_BULLUSER
+	      RETURN
+ 	   END IF
+	   REMOTE_FOUND = TEST2(NEW_FLAG,FOLDER_NUMBER)
+	END DO
+
+	CALL CLOSE_BULLUSER
+
+100	OPEN (UNIT=17,STATUS='UNKNOWN',IOSTAT=IER,RECL=256,
+     &		FILE=NODENAME(:TRIM(NODENAME))//'::"TASK=BULLETIN1"')
+
+	IF (IER.EQ.0) THEN
+	   IER = 0
+	   I = 1
+	   DO WHILE (IER.EQ.0.AND.I.LT.BLENGTH)
+	      WRITE (17,'(4A)',IOSTAT=IER)
+     &		15,-1,I,BMESSAGE(I:MIN(BLENGTH,I+127))
+	       I = I + 128
+	   END DO
+	   IF (IER.EQ.0) WRITE (17,'(7A)',IOSTAT=IER)
+     &		15,BLENGTH,I,ALL,CLUSTER,FOLDER_NUMBER,FOLDER
+	ELSE
+	   WRITE (6,'('' BULLCP not responding to request to'',
+     &	              '' broadcast to other nodes.'')')
+	   CALL GET_INPUT_PROMPT(RESPONSE,LEN,
+     &		'Want to try again? (Y/N with Y as default): ')
+	   IF (RESPONSE(:1).NE.'n'.AND.RESPONSE(:1).NE.'N') THEN
+	      WRITE (6,'('' Trying again...'')')
+	      GO TO 100
+	   ELSE
+	      WRITE (6,'('' Broadcast aborting. '',
+     &		         ''Continuing with message addition.'')')
+	   END IF
+	END IF
+
+	CLOSE (UNIT=17)
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION ERROR_TRAP
+
+	ERROR_TRAP = 1
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REPLY
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /INDESCRIP/ INDESCRIP
+	CHARACTER*(INPUT_LENGTH) INDESCRIP
+
+	IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	   WRITE(6,'('' ERROR: You have not read any message.'')')
+	   RETURN			! And return
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+
+	IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	   WRITE(6,'('' ERROR: Bulletin was not found.'')')
+	   CALL CLOSE_BULLDIR		! If not, then error out
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLFIL_SHARED
+
+	ILEN = LINE_LENGTH + 1
+
+	CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	END IF
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	   INDESCRIP = INPUT(7:)
+	ELSE
+	   INDESCRIP = DESCRIP
+	END IF
+
+	CALL CLOSE_BULLFIL
+
+	CALL CLOSE_BULLDIR
+
+	WRITE (6,'('' Adding REPLY message with the subject:'')')
+	IF (STREQ(INDESCRIP(:3),'RE:')) THEN
+	   INDESCRIP = 'Re:'//INDESCRIP(4:)
+	ELSE
+	   INDESCRIP = 'Re: '//INDESCRIP
+	END IF
+	WRITE (6,'(1X,A)') INDESCRIP(:TRIM(INDESCRIP))
+
+	CALL ADD
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CRELNM(INPUT,OUTPUT)
+	
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PSLDEF)'
+
+	INCLUDE '($LNMDEF)'
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT))
+	CALL END_ITMLST(CRELNM_ITMLST)
+
+	IER = SYS$CRELNM(,'LNM$PROCESS',INPUT,PSL$C_USER,
+     &		%VAL(CRELNM_ITMLST))
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETPRIV
+C
+C  SUBROUTINE GETPRIV
+C
+C  FUNCTION:
+C	To get process privileges.
+C  OUTPUTS:
+C	PROCPRIV - Returned privileges
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	COMMON /REALPROC/ REALPROCPRIV(2)
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(8,JPI$_PROCPRIV,%LOC(PROCPRIV))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	REALPROCPRIV(1) = PROCPRIV(1)
+	REALPROCPRIV(2) = PROCPRIV(2)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION SETPRV_PRIV
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+	DATA NEEDPRIV/0,0/
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	IF (NEEDPRIV(1).EQ.0.AND.NEEDPRIV(2).EQ.0) THEN
+	   CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+	   CALL READ_USER_FILE_HEADER(IER)
+	   CALL CLOSE_BULLUSER
+	   NEEDPRIV(1) = USERPRIV(1)
+	   NEEDPRIV(2) = USERPRIV(2)
+	END IF
+
+	IF ((PROCPRIV(1).AND.NEEDPRIV(1)).NE.0.OR.
+     &	    (PROCPRIV(2).AND.NEEDPRIV(2)).NE.0) THEN
+	   SETPRV_PRIV = .TRUE.
+	ELSE
+	   SETPRV_PRIV = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION OPER_PRIV
+	IMPLICIT INTEGER (A-Z)
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+	INCLUDE '($PRVDEF)'
+	OPER_PRIV = BTEST(PROCPRIV(1),PRV$V_OPER)
+	RETURN
+	END
+
+
+ 
+	SUBROUTINE GETUSER(USERNAME)
+C
+C  SUBROUTINE GETUSER
+C
+C  FUNCTION:
+C	To get username of present process.
+C  OUTPUTS:
+C	USERNAME   -   Username owner of present process.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	CHARACTER*(*) USERNAME		! Limit is 12 characters
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(LEN(USERNAME),JPI$_USERNAME,%LOC(USERNAME))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION CAPTIVE(FLAG)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE '($UAIDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	DATA READ_UAI/.FALSE./
+
+	COMMON /BULL_CUSTOM/ BULL_CUSTOM
+
+	IF (BTEST(BULL_CUSTOM,FLAG)) THEN 
+	   CAPTIVE = .FALSE.
+	   RETURN
+	END IF
+
+	TYPE = 1
+
+	IF (.NOT.READ_UAI) THEN
+	   CALL INIT_ITMLST
+	   CALL ADD_2_ITMLST(4,UAI$_FLAGS,%LOC(FLAGS))
+	   CALL END_ITMLST(GETUAI_ITMLST)
+           IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+	   READ_UAI = .TRUE.
+	END IF
+
+	CAPTIVE = ((FLAGS.AND.(UAI$M_CAPTIVE.OR.UAI$M_RESTRICTED)).NE.0
+     &	  .AND.1).OR.ISHFT(((FLAGS.AND.UAI$M_NOMAIL).NE.0).AND.1,1)
+
+	RETURN
+	END
+
+
+
+
+        SUBROUTINE SPAWN_PROCESS
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+	CHARACTER*256 COMMAND
+
+	IF (CAPTIVE(-1)) THEN
+	   WRITE (6,'('' ERROR: SPAWN not allowed from CAPTIVE account.'')')
+	   RETURN
+	END IF
+
+	CALL DISABLE_PRIVS
+
+	SAVE_KEYPAD_MODE = KEYPAD_MODE
+	IF (KEYPAD_MODE.EQ.0) CALL SET_KEYPAD
+
+	IF (CLI$PRESENT('COMMAND')) THEN
+	   CALL CLI$GET_VALUE('COMMAND',COMMAND,CLEN)
+	   COMMAND = '$'//COMMAND(:CLEN)
+	   CALL LIB$SPAWN(COMMAND(:CLEN+1))
+	ELSE
+           CALL LIB$SPAWN()
+	END IF
+
+	IF (SAVE_KEYPAD_MODE.EQ.0) CALL SET_NOKEYPAD
+
+	CALL ENABLE_PRIVS
+
+	RETURN
+        END
+
+
+        SUBROUTINE ATTACH
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	INCLUDE '($JPIDEF)'
+
+	CHARACTER*16 PROCESS
+
+	IF (CLI$PRESENT('PROCESS')) THEN
+	   CALL CLI$GET_VALUE('PROCESS',PROCESS,PLEN)
+
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(4,JPI$_PID,%LOC(PROCESS_ID))
+	   CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	   IER = SYS$GETJPIW(,,PROCESS(:PLEN),%VAL(GETJPI_ITMLST),,,,)
+	ELSE
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(4,JPI$_OWNER,%LOC(PROCESS_ID))
+	   CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	   IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)
+	END IF
+
+	IER = SYS$CANCEL(%VAL(TERM_CHAN))
+
+	SAVE_KEYPAD_MODE = KEYPAD_MODE
+	IF (KEYPAD_MODE.EQ.0) CALL SET_KEYPAD
+
+	IF (IER) IER = LIB$ATTACH(PROCESS_ID)
+	IF (.NOT.IER) CALL SYS_GETMSG(IER)
+
+	IF (SAVE_KEYPAD_MODE.EQ.0) CALL SET_NOKEYPAD
+
+	RETURN
+        END
+
+
+
+
+
+	SUBROUTINE GET_BROADCAST_MESSAGE(RING_BELL)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($BRKDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+C
+C  The largest message that can be broadcasted is dependent on system
+C  and user quotas.  The following limit is 12 lines of ( 80 characters +
+C  CR/LF ) + 2 bells.  This should be more than enough room, as broadcasts
+C  shouldn't be too large anyway.
+C
+
+	PARAMETER CR=CHAR(13),LF=CHAR(10),BELL=CHAR(7)
+
+	PARAMETER BRDCST_LIMIT = 82*12 + 2 + 2
+	CHARACTER*(BRDCST_LIMIT) BROAD
+
+	COMMON /BROAD_MESSAGE/ BROAD,BLENGTH
+
+	IF (RING_BELL) THEN	! Include BELL in message?
+	   BROAD(:36) =			! Say who the bulletin is from
+     &		BELL//BELL//CR//LF//LF//'NEW BULLETIN FROM: '//FROM
+	   BLENGTH = 37			! Start adding next line here
+	ELSE
+	   BROAD(:34) =			! Say who the bulletin is from
+     &		CR//LF//LF//'NEW BULLETIN FROM: '//FROM
+	   BLENGTH = 35			! Start adding next line here
+	END IF
+
+	IF (REMOTE_SET) REWIND (UNIT=3)
+
+	END = 0
+	ILEN = LINE_LENGTH + 1
+	I = 0
+	DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	   IF (REMOTE_SET) THEN
+	      READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	      IF (IER.NE.0) RETURN
+	   ELSE
+	      CALL GET_BULL_LINE(NBLOCK+1,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0) I = I + 1
+	   IF (ILEN.GT.0.AND.(I.GT.2.OR.(INPUT(:6).NE.'From: '.AND.
+     &			INPUT(:6).NE.'Subj: '))) THEN
+	      END = BLENGTH + ILEN - 1 + 2	! Check how long string will be
+	      IF (END.GT.BRDCST_LIMIT) RETURN	! String too long?
+	      BROAD(BLENGTH:END) = CR//LF//INPUT(:ILEN)! Else add new input
+	      BLENGTH = END + 1			! Reset pointer
+	   END IF
+	END DO
+
+	RETURN
+
+	ENTRY BROADCAST(ALL,CLUSTER)
+
+	CALL SYS$SETRWM(%VAL(1))		! Don't wait if can't broadcast
+
+	IF (ALL) THEN				! Should we broadcast to ALL?
+	   IF (CLUSTER) THEN
+	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLTERMS),,,%VAL(BRK$M_CLUSTER),,%VAL(5),,)
+	   ELSE
+	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLTERMS),,,,,%VAL(5),,)
+	   END IF
+	ELSE	 				! Else just broadcast to users.
+	   IF (CLUSTER) THEN
+	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLUSERS),,,%VAL(BRK$M_CLUSTER),,%VAL(5),,)
+	   ELSE
+	       CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLUSERS),,,,,%VAL(5),,)
+	   END IF
+	END IF
+
+	CALL SYS$SETRWM(%VAL(0))
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_FOLDER_INFO(IER)
+C
+C  SUBROUTINE GET_FOLDER_INFO
+C
+C  FUNCTION: Obtains & verifies folder names from command line.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	CHARACTER NODE_TEMP*256
+
+	NODE_NUM = 0				! Initialize number of nodes
+	DO WHILE (CLI$GET_VALUE('SELECT_FOLDER',NODE_TEMP)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified nodes
+	   IER = SYS_TRNLNM(NODE_TEMP,NODE_TEMP)
+	   CALL STR$UPCASE(NODE_TEMP,NODE_TEMP)
+	   DO WHILE (TRIM(NODE_TEMP).GT.0)
+	      NODE_NUM = NODE_NUM + 1
+	      COMMA = INDEX(NODE_TEMP,',')
+	      IF (COMMA.GT.0) THEN
+		 NODES(NODE_NUM) = NODE_TEMP(:COMMA-1)
+		 NODE_TEMP = NODE_TEMP(COMMA+1:)
+	      ELSE
+		 NODES(NODE_NUM) = NODE_TEMP
+		 NODE_TEMP = ' '
+	      END IF
+	      NLEN = TRIM(NODES(NODE_NUM))
+	      IF (NODES(NODE_NUM)(NLEN-1:NLEN).EQ.'::') THEN
+		 NODES(NODE_NUM) = NODES(NODE_NUM)(:NLEN)//'GENERAL'
+	      END IF
+	      FOLDER_NUMBER = -1
+	      FOLDER1 = NODES(NODE_NUM)
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (.NOT.IER) THEN
+		 WRITE (6,'('' Unable to access folder '',A)')
+     &				NODES(NODE_NUM)
+		 RETURN
+	      ELSE IF (READ_ONLY) THEN
+		 WRITE (6,'('' ERROR: No write access for folder '',A)')
+     &				NODES(NODE_NUM)
+		 IER = 0
+		 RETURN
+	      END IF
+	   END DO
+	END DO
+
+	IER = 1
+
+	RETURN
+	END
+	
+
+
+
+	SUBROUTINE INIT_BULLETIN(NOX)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /READIT/ READIT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING /.FALSE./
+	DATA PAGE_LENGTH/24/,PAGE_WIDTH/80/
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	EXTERNAL ERROR_TRAP
+	EXTERNAL BULLETIN_MAINCOMMANDS,ENABLE_CTRL_EXIT
+	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED
+
+	PARAMETER PCB$M_BATCH = '4000'X
+	PARAMETER PCB$M_NETWRK = '200000'X
+	PARAMETER LIB$M_CLI_CTRLY = '2000000'X
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /DEF_PROT/ ORIGINAL_DEF_PROT
+
+	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
+	CHARACTER*44 PROMPT
+
+	COMMON /BULL_CUSTOM/ BULL_CUSTOM
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/
+
+	COMMON /DCL/ DCL_CMD,DCL_COMMAND
+	CHARACTER DCL_CMD*132
+
+	IER = SYS_TRNLNM_SYSTEM('BULL_CUSTOM',BULL_PARAMETER)	
+	IF (IER) IER = OTS$CVT_TZ_L(BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+     &		,BULL_CUSTOM,,,%VAL(1)) 
+
+	CALL LIB$GET_FOREIGN(INCMD)
+	DCL_COMMAND = INDEX(INCMD,' "').GT.0.OR.INCMD(:1).EQ.'"'
+
+	CALL LIB$ESTABLISH(ERROR_TRAP)
+        IF (.NOT.CLI$GET_VALUE('PROMPT',COMMAND_PROMPT,ILEN)) THEN
+           CALL LIB$REVERT
+           CALL CLI$GET_VALUE('$LINE',COMMAND_PROMPT,ILEN)
+	   INCMD = 'BULLETIN '//INCMD
+           CALL CLI$DCL_PARSE(INCMD,BULLETIN_MAINCOMMANDS)
+        ELSE
+           CALL LIB$REVERT
+        END IF
+
+	IF (DCL_COMMAND) THEN
+	   IER = CLI$GET_VALUE('SELECT_FOLDER',DCL_CMD,LENP)
+	   IF (LENP.GT.0) THEN
+	      IF (DCL_CMD(LENP:LENP).EQ.'"') DCL_CMD = DCL_CMD(:LENP-1)
+	      IF (DCL_CMD(:1).EQ.'"') DCL_CMD = DCL_CMD(2:)
+	   END IF
+	END IF
+
+	READIT = 0
+
+	LOGIN_SWITCH = CLI$PRESENT('LOGIN')
+	SYSTEM_SWITCH = CLI$PRESENT('SYSTEM')
+	REVERSE_SWITCH = CLI$PRESENT('REVERSE')
+
+	IER = LIB$SYS_TRNLOG('BULL_DISABLE',LEN_P,BULL_PARAMETER)
+	IF (IER.EQ.1.AND.LEN_P.GT.0.AND..NOT.CLI$PRESENT('STOP')
+     &	    .AND.BULL_PARAMETER(:LEN_P).NE.'ENABLE') THEN
+	   IF (.NOT.LOGIN_SWITCH) THEN
+	      WRITE (6,'('' BULLETIN temporarily disabled. Try later.'')')
+	   END IF
+	   CALL EXIT
+	END IF
+
+	CALL SYS$SETDFPROT(,ORIGINAL_DEF_PROT)
+		! Save original default protection in case it gets changed
+
+	CALL DCLEXH(%LOC(ENABLE_CTRL_EXIT))		! Declare exit handler
+
+C
+C  Check to see if CONTROL Y disabled.  If so, then never disable CONTROL Y.
+C  Disabling and enabling CONTROL Y is done so that a person can not break
+C  while one of the data files is opened, as that would not allow anyone
+C  else to modify the files.  However, if CONTROL Y is already disabled,
+C  this is not necessary, and should not be done!
+C
+
+	CALL LIB$DISABLE_CTRL(LIB$M_CLI_CTRLY,CTRLY)	! Disable CTRL-Y & -C
+	CTRLY = CTRLY .AND. LIB$M_CLI_CTRLY
+	CALL GETPRIV				! Check privileges
+	IF (NOX) CALL CHECK_PRIV_IO(ERR)			! Check privileges on output I/O
+	CALL CHECK_DIR_ACCESS()			! Check access to directories
+	CALL LIB$ESTABLISH(ERROR_TRAP)
+        IF (CLI$GET_VALUE('LIBRARY',BULL_PARAMETER,LEN_P)) THEN
+	   FOLDER_DIRECTORY = BULL_PARAMETER(:LEN_P)
+	   CALL CHECK_DIR(BULL_PARAMETER,.FALSE.)
+	   FOLDER_DIRECTORY = BULL_PARAMETER
+	   CALL ADD_DIRECTORIES
+        END IF
+        CALL LIB$REVERT
+	CALL LIB$ENABLE_CTRL(CTRLY,)		! Renable CTRLY-Y & -C
+
+	IF (ERR.EQ.1) CALL EXIT			! I/O privilege error, so exit
+
+	CALL GETUSER(USERNAME)		! Get the process's username
+	IF (.NOT.LOGIN_SWITCH) CALL CHECK_BULLETIN_PRIV(USERNAME)
+					! Check if has bulletin privileges
+
+	I = 1				! Strip off folder name if specified
+	DO WHILE (I.LE.ILEN)
+	   IF (COMMAND_PROMPT(I:I).EQ.' ') THEN
+	      COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
+	      I = ILEN + 1
+	   ELSE IF (COMMAND_PROMPT(I:I).EQ.'/') THEN
+	      COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
+	      I = ILEN + 1
+	   ELSE
+	      I = I + 1
+	   END IF
+	END DO
+	ILEN = 1			! Get executable name to use as prompt
+	DO WHILE (ILEN.GT.0)
+	   ILEN = MAX(INDEX(COMMAND_PROMPT,':'),INDEX(COMMAND_PROMPT,']'))
+	   IF (ILEN.GT.0) THEN
+	      COMMAND_PROMPT = COMMAND_PROMPT(ILEN+1:)
+	   ELSE
+	      DO I=TRIM(COMMAND_PROMPT),1,-1
+		 IF (COMMAND_PROMPT(I:I).LT.'A'.OR.
+     &			COMMAND_PROMPT(I:I).GT.'Z') THEN
+		    COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
+		 END IF
+	      END DO
+	   END IF
+	END DO
+	COMMAND_PROMPT = COMMAND_PROMPT(:TRIM(COMMAND_PROMPT))//'> '
+	IF (COMMAND_PROMPT.EQ.'RUN> '.OR.COMMAND_PROMPT.EQ.'RU> '.OR.
+     &	    COMMAND_PROMPT.EQ.'R> ') COMMAND_PROMPT = 'BULLETIN> '
+
+	CALL INIT_COMPRESS
+
+	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//FOLDER
+
+	CALL CLI$GET_VALUE('SEPARATE',SEPARATE)
+
+	IF (CLI$PRESENT('EDIT')) EDIT_DEFAULT = .TRUE.	! /EDIT switch test
+
+	CALL FIND_BULLCP			! See if BULLCP is running
+
+	IF (CLI$PRESENT('CLEANUP')) THEN	! Test for /CLEANUP switch
+	   CALL CLI$GET_VALUE('CLEANUP',BULL_PARAMETER,LEN_P) ! Get folder #
+	   READ (BULL_PARAMETER,'(I<LEN_P>)') FOLDER_NUMBER
+	   CALL SELECT_FOLDER(.FALSE.,IER)	! Select folder
+	   CALL CLEANUP_BULLFILE		! Cleanup empty blocks
+	   CALL EXIT				! all done with cleanup
+	ELSE IF (CLI$PRESENT('BBOARD')) THEN	! Test for /BBOARD switch
+	   CALL BBOARD				! look for BBOARD mail
+	   CALL EXIT				! all done with BBOARD
+	ELSE IF (CLI$PRESENT('STARTUP').OR.	! BULLCP process control
+     &	         CLI$PRESENT('STOP')) THEN
+	   CALL CREATE_BULLCP
+	ELSE IF (CLI$PRESENT('BULLCP')) THEN	! This is BULLCP, so start
+	   IF (.NOT.CLI$GET_VALUE('SELECT_FOLDER',
+     &				BULL_PARAMETER,LENP)) THEN
+	      CALL RUN_BULLCP			! doing what BULLCP does!
+	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'NEWS') THEN
+	      CALL NEWS2BULL(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'NEWS1') THEN
+	      CALL NEWS2BULL(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'SMTP') THEN
+	      CALL SEND_MAIL
+	   END IF
+	END IF
+
+	CALL GETSTS(STS)			! Get process status word
+
+	IF (SYSTEM_SWITCH.OR.LOGIN_SWITCH) THEN	! If BULLETIN/LOGIN or /SYSTEM
+	   IF ((STS.AND.PCB$M_BATCH).GT.0) CALL EXIT	! If BATCH, exit
+	   IF (NOX) CALL CRELNM('SYS$INPUT','TT')	! Input from terminal
+	END IF
+
+	IF ((STS.AND.PCB$M_NETWRK).EQ.0) THEN
+	   DECNET_PROC = .FALSE.
+	   ERROR_UNIT = 6
+
+	   IF (NOX) CALL ASSIGN_TERMINAL		! Assign terminal
+
+           CALL LIB$ESTABLISH(ERROR_TRAP)       ! Do again due to possible
+           IF (.NOT.CLI$PRESENT('PROMPT')) THEN ! KEYPAD init file.
+              CALL LIB$REVERT
+              CALL CLI$DCL_PARSE(INCMD,BULLETIN_MAINCOMMANDS)
+           ELSE
+              CALL LIB$REVERT
+           END IF
+
+	   IF (.NOT.LOGIN_SWITCH) THEN
+	      INCMD = 'SELECT'	! Causes nearest folder name to be selected
+	      CALL SELECT_FOLDER(.FALSE.,IER)	! Select GENERAL folder
+	      IF (.NOT.IER) RETURN			! If can't access, exit
+
+	      IF (.NOT.TEST_BULLCP()) CALL DELETE_EXPIRED
+						! Delete expired messages
+	   END IF
+
+C
+C  Get user info stored in SYS$LOGIN.  Currently, this simply stores
+C  the time of the latest message read for each folder.
+C
+
+	   CALL OPEN_USERINFO
+
+	   CALL OPEN_OLD_TAG
+
+	   IF (.NOT.NOX) THEN
+	      CALL NEW_MESSAGE_NOTIFICATION
+	      RETURN
+	   END IF
+
+C
+C  Get page size for the terminal.
+C
+
+	   CALL GETPAGSIZ(PAGE_LENGTH,PAGE_WIDTH)
+
+	   IER = CLI$GET_VALUE('WIDTH',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) PAGE_WIDTH
+	   END IF
+
+	   IF (CLI$PRESENT('PAGE')) PAGING = .TRUE.
+	   IF ((STS.AND.PCB$M_BATCH).GT.0) THEN
+	      PAGING = .FALSE.
+	      PAGE_WIDTH = 80
+	   END IF
+
+	   IF (SYSTEM_SWITCH) THEN
+	      IER = CLI$GET_VALUE('SYSTEM',BULL_PARAMETER,LEN_P)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Days specified?
+	         CALL SUBTIME(SYSTEM_LOGIN_BTIM,BULL_PARAMETER(:LEN_P),IER)
+		 IF (.NOT.IER) THEN
+		    WRITE (6,'('' ERROR: Invalid parameter in /SYSTEM.'')')
+		    CALL EXIT
+		 END IF
+	      END IF
+	      IF (.NOT.LOGIN_SWITCH) THEN
+	         CALL MODIFY_SYSTEM_LIST(0)
+                 CALL READ_IN_FOLDERS
+		 FOLDER_Q = SAVE_FOLDER_Q1
+		 DO I = 1,SAVE_FOLDER_NUM
+	   	    CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	            IF (TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+		       CALL SHOW_SYSTEM
+		    END IF
+	         END DO
+	      END IF
+	   END IF
+
+C
+C  If /LOGIN, display SYSTEM bulletins and subject of non-SYSTEM bulletins.
+C
+
+	   IF (LOGIN_SWITCH.OR.SYSTEM_SWITCH) THEN	! Is /LOGIN present?
+	      CALL LOGIN			! Display SYSTEM bulletins
+	      IF (READIT.EQ.0) CALL EXIT	! If no READNEWs not set, exit
+	   END IF
+
+C
+C  If new bulletins have been added since the last time bulletins have been
+C  read, position bulletin pointer so that next bulletin read is the first new
+C  bulletin, and alert user.  If READNEW set and no new bulletins, just exit.
+C
+
+	   IF (.NOT.DCL_COMMAND) CALL NEW_MESSAGE_NOTIFICATION
+	ELSE
+	   IF (TEST_BULLCP()) CALL EXIT
+	   DECNET_PROC = .TRUE.
+	   ERROR_UNIT = 5
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin.hlp b/decus/vmslt00a/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..8479322b066d027b272d870144184edbbae1c7b2
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin.hlp
@@ -0,0 +1,151 @@
+1 BULLETIN
+Invokes  the  PFC  BULLETIN  Utility.  This utility is used for reading,
+adding and deleting message.  Users are notified at login time that new
+messages have been added and the topics of those messages are displayed.
+Reading of those messages is optional.  (Use  the  command  SET  READNEW
+while  in BULLETIN for setting automatic reading.)  Privileged users can
+add system bulletins that are displayed in full at  login  time.   These
+messages  are  also  saved,  and  can be read by BULLETIN.  Messages are
+automatically deleted after a specified expiration  date,  or  they  can
+manually  be  deleted  by  either  the  submitter  of  the  message or a
+privileged user.
+
+ Format:
+
+      BULLETIN [foldername or bulletin interactive command]
+
+BULLETIN has an interactive help  available  while  using  the  utility.
+Type HELP after invoking the BULLETIN command.
+
+If so configured, BULLETIN can also read USENET NEWS.
+2 Description
+
+The  BULLETIN  utility  is  a  utility to display messages to users when
+logging in.  Users are notified of  messages  only  once.   They're  not
+forced into reading them every time they log in.  Submitting and reading
+messages is easy to do via a utility similar to the  VMS  MAIL  utility.
+Privileged users can create messages which are displayed in full. (known
+as SYSTEM  messages).   Non-privileged  users  may  be  able  to  create
+non-SYSTEM  messages  (unless  your  system  manager  has  disabled  the
+feature), but only topics are displayed at login.
+
+Folders can be created so that messages pertaining to a single topic can
+be  placed  together.   Folders  can be made private so that reading and
+writing is limited to only users  or  groups  who  are  granted  access.
+Alternatively,  folders  can  be  made  semi-private in that everyone is
+allowed to read them but write access is limited.
+
+When new non-system messages are displayed, an optional feature which  a
+user  may  enable  will cause BULLETIN to ask whether the user wishes to
+read the new bulletins. The user can then read the  messages  (with  the
+ability  to  write any of the messages to a file). A user can enable the
+notification and prompting of new  messages  feature  on  a  folder  per
+folder  basis.   However,  the  exception  is  messages submitted to the
+default GENERAL folder.  Users are  always  notified  at  login  of  new
+bulletins  in  this  folder,  but can disable the prompting.  This is to
+give non-privileged users some ability to force  a  notification  of  an
+important message.
+
+Messages have expiration dates and times, and are deleted automatically.
+Expiration dates and  times  can  be  specified  in  absolute  or  delta
+notation.   Privileged  users  can  specify  "SHUTDOWN"  messages,  i.e.
+messages  that  get  deleted  after  a  system  shutdown  has  occurred.
+"PERMANENT" messages can also be created which never expire.
+
+Privileged users can broadcast their message (to either all users or all
+terminals).
+
+A user can select, on a folder per  folder  basis,  to  have  a  message
+broadcast  to  their  terminal  immediately  notifying  them  when a new
+message has been added.
+
+An optional "Bulletin Board" feature allows messages to  be  created  by
+users  of  other  systems  connected  via  networks.   A username can be
+assigned to a folder, and any mail sent to that  user  is  converted  to
+messages  and  stored  in  that  folder.   This  feature  originally was
+designed to duplicate the message board  feature  that  exists  on  some
+Arpanet  sites.  However, with the addition of folders, another possible
+use is to assign an Arpanet mailing list to a folder. For  example,  one
+could  have  an  INFOVAX folder associated with an INFOVAX username, and
+have INFO-VAX mail sent to INFOVAX.  Users could then read  the  mailing
+list  in  that  folder,  rather  than having INFO-VAX sent to each user.
+Optionally, the input for the bulletin board can be directed to be taken
+from  any  source other than VMS MAIL.  This might be useful if incoming
+mail is stored in a different place other than VMS MAIL.
+
+Messages can be either sent to a file, to a print queue,  or  mailed  to
+another user.
+
+BULLETIN  can  also  act a USENET NEWS reader if the appropriate network
+software is available to interact with.  See the installation notes  for
+more detail.
+2 Parameters
+The  parameter  following  the  BULLETIN  command  is interpreted as the
+folder name which should be selected, rather than  the  default  GENERAL
+folder.   If  the  parameter is specified with quotes ("parameter"), the
+parameter is  interpreted  as  an  interactive  BULLETIN  command,  i.e.
+commands  which are entered once BULLETIN is executed, i.e. "DIRECTORY",
+"ADD", etc.  BULLETIN will exit immediately after entering that command,
+rather than prompting for another command.  More than one command can be
+specified by separating the  commands  with  semi-colons,  i.e.  "SELECT
+DATA;DIR".  If the last command ends with a semi-colon, then BULLETIN 
+will not exit, but instead will enter the standard interactive mode and
+prompt the user for commands.
+2 /EDIT
+Specifies that all ADD or REPLACE commands within BULLETIN will select
+the editor for inputting text.
+2 /KEYPAD
+ /[NO]KEYPAD
+Specifies that keypad mode is to be set on, such that the keypad keys
+correspond to BULLETIN commands.  The default is /KEYPAD.
+2 /LIBRARY
+ /LIBRARY=library
+
+Specifies the library of folders to use.  By default there is  only  one
+library.  However, the system manager may decide to create more than one
+library, with each library saved in a different directory.  Use the SHOW
+LIBRARY/ALL command within BULLETIN to see if there are other libraries. 
+2 /PAGE
+ /[NO]PAGE
+
+Specifies  whether BULLETIN will stop outputting when it displays a full
+screen or not.  /PAGE is the default.   If  /NOPAGE  is  specified,  any
+output  will  continue  until it finishes.  This is useful if you have a
+terminal which can store several screenfuls of display in its memory.
+2 /PGFLQUOTA
+   /PGFLQUOTA=pages
+
+Used if you want to specify the page file quota for the BULLCP process.
+2 /STARTUP
+Starts up a detached process which will periodically check for expired
+messages, cleanup empty space in files, and convert BBOARD mail to
+messages.  This is recommended to avoid delays when invoking BULLETIN.
+It will create a process with the name BULLCP.  For clusters, this
+need be done only on one node.  On all other nodes, the system logical
+name BULL_BULLCP should be defined (to anything) in order that BULLETIN
+is aware that it is running on another node. (On the local node where
+BULLCP is running, this logical name is automatically defined.)
+2 /STOP
+Stops the BULLCP process without restarting a new one.  (See /STARTUP
+for information on the BULLCP process.)
+2 /SYSTEM
+   /SYSTEM=[days]
+
+Displays system messages that have been recently added.  The default is
+to show the messages that were added during the last 7 days.  This can
+be modified by specifying the number of days as the parameter.
+This command is useful for easily redisplaying system messages that
+might have been missed upon logging in (or were broadcasted but were
+erased from the screen.)
+2 /WIDTH
+   /WIDTH=page_width
+
+Specifies the terminal width for display purposes.  This is used if your
+startup procedure is configured such that BULLETIN/LOGIN is executed before
+the terminal type is known, and the default width is larger than what the
+terminal type actually is.  I.e. the default width might be 132, but the
+real width is 80.  In that case, you should add /WIDTH=80 to BULLETIN/LOGIN.
+2 /WSEXTENT
+   /WSEXTENT=pages
+
+Used if you want to specify the working set limit for the BULLCP process.
diff --git a/decus/vmslt00a/bulletin/bulletin.lnk b/decus/vmslt00a/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..f0fed2c6aa53cdb374e159094bf7567935b78aaf
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin.lnk
@@ -0,0 +1,18 @@
+$ ULIB = "NONE"
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .NES. "" THEN GOTO LINK
+$ IF F$TRNLNM("TWG$TCP") .EQS. "" THEN GOTO LINK
+$ ULIB = "PROCESS"
+$ DEFINE/USER LNK$LIBRARY TWG$TCP:[NETDIST.LIB]LIBNET
+$ DEFINE/USER LNK$LIBRARY_1 TWG$TCP:[NETDIST.LIB]LIBNETACC
+$ DEFINE/USER LNK$LIBRARY_2 TWG$TCP:[NETDIST.LIB]LIBNET
+$LINK:
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN GOTO ALINK
+$ LINK/NOTRACE BULL/LIB/INC=BULLETIN$MAIN,SYS$SYSTEM:SYS.STB/SEL-
+        /USERLIB='ULIB'/EXE=BULLETIN,SYS$INPUT/OPT
+SYS$SHARE:VAXCRTL/SHARE
+ID="V2.3"
+$ EXIT
+$ALINK:
+$ LINK/NOTRACE/NONATIVE_ONLY BULL/LIB/INC=BULLETIN$MAIN/SYSEXE-
+       /USERLIB='ULIB'/EXE=BULLETIN,SYS$SHARE:VAXCRTL/LIB,SYS$INPUT/OPT
+ID="V2.5"
diff --git a/decus/vmslt00a/bulletin/bulletin0.for b/decus/vmslt00a/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..39a50c49614a4fe705cb407226225e9f644ddedb
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin0.for
@@ -0,0 +1,2575 @@
+C
+C  BULLETIN0.FOR, Version 11/9/99
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE DELETE_MSG
+C
+C  SUBROUTINE DELETE_MSG
+C
+C  FUNCTION:  Deletes a bulletin entry from the bulletin file.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER ANSWER*4,REMOTE_USER*12,SUBJECT*56
+
+	IMMEDIATE = 0
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   FORCE = .TRUE.
+	ELSE	
+	   FORCE = CLI$PRESENT('FORCE')
+	   IF (CLI$PRESENT('IMMEDIATE')) THEN
+	      IF (REMOTE_SET.EQ.4) THEN
+	         WRITE (6,'('' IMMEDIATE not valid for news group.'')') 
+	         RETURN
+	      ELSE
+	         IMMEDIATE = 1
+	      END IF
+           END IF
+	END IF
+
+	IF (CLI$PRESENT('NODES')) THEN	! Delete messages on DECNET node?
+	   CALL DELETE_NODE		! Yes...
+	   RETURN
+	ELSE IF (DECNET_PROC) THEN	! Is this from remote node?
+	   IER = CLI$GET_VALUE('SUBJECT',SUBJECT,SLEN)
+	   CALL STR$UPCASE(SUBJECT,SUBJECT)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(0,IER)
+	   DEL_BULL = 0
+	   IER = 1
+	   DO WHILE (DEL_BULL+1.EQ.IER)
+	      DEL_BULL = DEL_BULL + 1
+	      CALL READDIR(DEL_BULL,IER)
+	      CALL STR$UPCASE(DESCRIP,DESCRIP)
+	      IF (DEL_BULL+1.EQ.IER.AND.USERNAME.EQ.FROM
+     &		   .AND.INDEX(DESCRIP,SUBJECT(:SLEN)).GT.0) THEN
+	         CALL REMOVE_ENTRY(DEL_BULL,DEL_BULL,DEL_BULL,IMMEDIATE)
+		 CALL CLOSE_BULLDIR
+	         WRITE (5,'(''END'')')	! Tell DECNET that delete went ok.
+		 RETURN
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLDIR		! Specified message not found,
+	   WRITE(ERROR_UNIT,1030)	! so error out.
+	   RETURN
+	END IF
+
+C
+C  Get the bulletin number to be deleted.
+C
+
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   SBULL = BULL_POINT		! Delete the file we are reading
+	   EBULL = SBULL
+	   IER = 0
+	ELSE
+	   IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	      CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+	   ELSE IF (CLI$PRESENT('ALL')) THEN
+	      SBULL = 1
+	      EBULL = F_NBULL
+	      IER = 0
+	   ELSE IF (BULL_POINT.EQ.0) THEN	! No.  Have we just read a bulletin?
+	      WRITE(6,1010)		! No, then error.
+	      RETURN
+	   ELSE
+	      SBULL = BULL_POINT		! Delete the file we are reading
+	      EBULL = SBULL
+	      IER = 0
+	   END IF
+	END IF
+
+	IF (SBULL.LE.0.OR.IER.NE.0) THEN
+	   WRITE (6,1020)
+	   RETURN
+	ELSE IF (EBULL.GT.F_NBULL.AND..NOT.REMOTE_SET.AND.
+     &						SBULL.NE.EBULL) THEN
+	   WRITE (6,'('' Last message specified > number in folder.'')')
+	   WRITE (6,'('' Do you want to delete to end of folder? '',$)')
+	   READ (5,'(A)',IOSTAT=IER) ANSWER
+	   CALL STR$UPCASE(ANSWER,ANSWER)
+	   IF (ANSWER(:1).NE.'Y') THEN
+	      WRITE (6,'('' Deletion aborted.'')')
+	      RETURN
+	   ELSE
+	      EBULL = F_NBULL
+	   END IF
+	END IF
+
+C
+C  Check to see if specified bulletin is present, and if the user
+C  is permitted to delete the bulletin.
+C
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   IF (SBULL.NE.EBULL) THEN
+	      WRITE (6,1025)
+	      RETURN
+	   END IF
+	   IER1 = SBULL + 1
+	   IF (SBULL.NE.BULL_POINT) CALL READDIR(SBULL,IER1)
+	   SUBJECT = DESCRIP
+	   IER2 = 0
+	   IF (IER2.EQ.0.AND.IER1.EQ.SBULL+1) CALL 
+     &	    REMOTE_DELETE(SBULL,IMMEDIATE,SUBJECT,I,FOLDER1_COM,IER)     
+	   IF (IER.EQ.0.AND.REMOTE_SET.LT.3) THEN
+	      IF (I.EQ.LEN(FOLDER1_COM)) THEN
+	         IER = SYS$ASCTIM(,INPUT,F1_NEWEST_BTIM,)
+	         NEWEST_EXDATE = INPUT(:11)
+	         NEWEST_EXTIME = INPUT(13:23)
+	         NBULL = F1_NBULL
+	   	 CALL UPDATE_FOLDER
+	      ELSE
+	  	 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      END IF
+	   ELSE IF (IER.NE.0) THEN
+	      CALL DISCONNECT_REMOTE
+	   END IF
+	   RETURN
+	ELSE IF (REMOTE_SET.EQ.3) THEN
+	   BULL_DELETE = SBULL - 1
+	   IER = 0
+	   IF (CLI$PRESENT('REASON')) THEN 
+	      CALL CLI$GET_VALUE('REASON',BULL_PARAMETER,LEN_P)
+	   END IF
+	   DO WHILE (BULL_DELETE.LT.EBULL)
+	      BULL_DELETE = BULL_DELETE + 1
+	      DO WHILE (BULL_DELETE+1.NE.IER)
+	         CALL READDIR(BULL_DELETE,IER)	! Get info for bulletin
+	         IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	            BULL_DELETE = BULL_DELETE + 1
+	            IF (BULL_DELETE.GT.EBULL) RETURN
+	            IF (EBULL.EQ.SBULL) THEN
+		       WRITE(6,1030) 
+	               RETURN
+		    END IF
+	         END IF
+	      END DO
+	      SUBJECT = DESCRIP
+	      IF (.NOT.TEST_NEWS_OWNER().AND.SETPRV_PRIV().AND.
+     &		  .NOT.FORCE) THEN
+ 	         SUBJECT = 'CanceL'
+	         IF (CLI$PRESENT('REASON')) THEN 
+		    SUBJECT = SUBJECT(:6)//BULL_PARAMETER(:LEN_P)
+		 END IF
+	      END IF
+	      CALL REMOTE_DELETE
+     &			(SBULL,IMMEDIATE,SUBJECT,I,FOLDER1_COM,IER)     
+	      IF (IER.NE.0) THEN
+		 CALL DISCONNECT_REMOTE
+	   	 RETURN
+	      END IF
+	   END DO
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLDIR
+
+	CALL READDIR(0,IER)
+
+	BULL_DELETE = SBULL - 1
+	DO WHILE (BULL_DELETE.LT.EBULL)
+	   BULL_DELETE = BULL_DELETE + 1
+	   DO WHILE (BULL_DELETE+1.NE.IER)
+	      CALL READDIR(BULL_DELETE,IER)	! Get info for bulletin
+	      IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	         IF (REMOTE_SET.EQ.4) THEN
+	            BULL_DELETE = BULL_DELETE + 1
+	            IF (BULL_DELETE.GT.EBULL) THEN
+		       CALL CLOSE_BULLDIR
+		       RETURN
+		    END IF
+	         ELSE
+	            IF (.NOT.CLI$PRESENT('ALL')) WRITE(6,1030) 
+	            CALL CLOSE_BULLDIR		! If not, then error out
+	            RETURN
+	         END IF
+	      END IF
+	   END DO
+
+	   SUBJECT = DESCRIP
+
+	   IF (USERNAME.NE.FROM.OR.(REMOTE_SET.EQ.4.AND.
+     &		.NOT.TEST_NEWS_OWNER())) THEN
+	      CALL STR$UPCASE(REMOTE_USER,FROM)
+	      IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.    ! Privileges?
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN
+	         WRITE(6,1040)		! No, then error out.
+	         CALL CLOSE_BULLDIR
+		 RETURN
+	      ELSE IF (SBULL.EQ.EBULL) THEN
+		 IF (TRIM(FROM).EQ.1) THEN
+		    CALL OPEN_BULLFIL
+	            ILEN = LINE_LENGTH + 1
+	            CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	            CALL CLOSE_BULLFIL
+	            ASK = ILEN.EQ.0.OR.INPUT(:6).NE.'From: '
+		 ELSE
+		    ASK = REMOTE_USER.NE.USERNAME
+		 END IF
+		 IF (ASK.AND..NOT.FORCE) THEN
+	            CALL CLOSE_BULLDIR
+	            WRITE (6,1050)	! Make sure user wants to delete it
+	            READ (5,'(A)',IOSTAT=IER) ANSWER
+	            CALL STR$UPCASE(ANSWER,ANSWER)
+	            IF (ANSWER(:1).NE.'Y') RETURN
+	            CALL OPEN_BULLDIR
+	            CALL READDIR(BULL_DELETE,IER)
+	            IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	               WRITE(6,1030)	! If not, then error out
+	               CALL CLOSE_BULLDIR
+		       RETURN
+	            END IF
+		    IF (REMOTE_SET.EQ.4) THEN 
+ 	               SUBJECT = 'CanceL'
+		    END IF
+	         END IF
+	      END IF
+	   END IF
+
+C
+C  Delete the bulletin directory entry.
+C
+	   CALL REMOVE_ENTRY(BULL_DELETE,SBULL,EBULL,IMMEDIATE)
+	   IF (REMOTE_SET.EQ.4) THEN
+	      IF (.NOT.CLI$PRESENT('LOCAL').AND.(TEST_NEWS_OWNER().OR.
+     &		  SETPRV_PRIV())) THEN
+	         CALL REMOTE_DELETE
+     &		    (BULL_DELETE,IMMEDIATE,SUBJECT,I,FOLDER1_COM,IER)
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLDIR
+	RETURN
+
+1010	FORMAT(' ERROR: You are not reading any message.')
+1020	FORMAT(' ERROR: Specified message number has incorrect format.')
+1025	FORMAT(' ERROR: Cannot delete multiple messages in remote folder.')
+1030	FORMAT(' ERROR: Specified message was not found.')
+1040	FORMAT(' ERROR: Message was not deleted. Not owned by you.')
+1050	FORMAT(' Message is not owned by you.',
+     &	       ' Are you sure you want to delete it? ',$)
+
+	END
+
+
+
+	SUBROUTINE REMOVE_ENTRY(BULL_DELETE,SBULL,EBULL,IMMEDIATE)
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	INTEGER NOW(2),EX(2)
+
+	IF (IMMEDIATE.EQ.1) THEN		! Delete it immediately
+
+	   CALL DELETE_ENTRY(BULL_DELETE)	! Delete the directory entry
+
+	   IF ((SYSTEM.AND.4).EQ.4) THEN	! Was entry shutdown bulletin?
+	      SHUTDOWN = SHUTDOWN - 1		! Decrement shutdown count
+	   END IF
+	ELSE				! Delete it eventually
+C
+C  Change year of expiration date of message to 100 years less,
+C  to indicate that message is to be deleted.  Then, set expiration date
+C  in header of folder to 15 minutes from now.  Thus, the folder will be
+C  checked in 15 minutes (or more), and will delete the messages then.
+C
+C  NOTE: If some comic set their expiration date to > 1999, then
+C  the deleted date will be set to 1899 since can't specify date <1859.
+C
+
+	   IF ((SYSTEM.AND.7).LE.1) THEN	! General or System message
+	      IF (EXDATE(8:9).EQ.'19') EXDATE(8:9) = '18'
+	      IF (EXDATE(8:9).EQ.'20') EXDATE(8:9) = '19'
+	      IF (EXDATE(8:9).EQ.'18'.AND.EXDATE(10:10).LT.'6')
+     &			EXDATE(10:11) = '99'
+	   ELSE				! Permanent or Shutdown
+	      IF (EXDATE(2:2).EQ.'-') THEN
+	         EXDATE = EXDATE(:6)//'19'//EXDATE(9:)
+	      ELSE
+	         EXDATE = EXDATE(:7)//'19'//EXDATE(10:)
+	      END IF
+	   END IF
+
+	   CALL WRITEDIR(BULL_DELETE,IER)	! Update message expiration date
+
+	   IER = SYS$BINTIM('0 0:15',EX)	! Get time 15 minutes from now
+	   IER = SYS$GETTIM(NOW)
+	   IER = LIB$SUBX(NOW,EX,EX)
+	   IER = SYS$ASCTIM(,INPUT,EX,)
+
+	END IF
+
+	IF (IMMEDIATE.NE.1.AND.BULL_DELETE.EQ.EBULL) THEN
+	   CALL READDIR(0,IER)			! Get header
+
+	   NEWEST_EXDATE = INPUT(:11)		! and store new expiration date
+	   NEWEST_EXTIME = INPUT(13:23)
+
+	   CALL WRITEDIR(0,IER)
+	   IF (REMOTE_SET.EQ.4) THEN
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+              CALL GET_MSGKEY(NEWEST_EXBTIM,NEWS_F_EXPIRED_DATE)
+	      CALL REWRITE_FOLDER_FILE(IER)
+	      CALL CLOSE_BULLNEWS 
+	   END IF
+	ELSE IF (BULL_DELETE.EQ.EBULL) THEN
+	   IF (REMOTE_SET.NE.4) CALL CLEANUP_DIRFILE(SBULL)
+				! Reorder directory file
+
+	   CALL UPDATE_ALWAYS	! Somewhat a kludgey way of updating latest
+				! bulletin and expired dates.
+
+	   IF (REMOTE_SET.NE.4.AND.SBULL.LE.BULL_POINT) THEN
+	      IF (BULL_POINT.GT.EBULL) THEN
+	         BULL_POINT = BULL_POINT - (EBULL - SBULL + 1)
+	      ELSE
+		 BULL_POINT = SBULL - 1
+	      END IF
+	   END IF		! Readjust where which bulletin to read next
+				! if deletion causes messages to be moved.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_2_VALS(INPUT,ILEN,SVAL,EVAL,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*(*) INPUT
+
+	DELIM = MAX(INDEX(INPUT,':'),INDEX(INPUT,'-'))
+
+	IF (DELIM.EQ.0) THEN
+	   DECODE(ILEN,'(I<ILEN>)',INPUT,IOSTAT=IER) SVAL
+	   EVAL = SVAL
+	ELSE
+	   DECODE(DELIM-1,'(I<DELIM-1>)',INPUT,IOSTAT=IER) SVAL
+	   CALL STR$UPCASE(INPUT,INPUT)
+	   IF (IER.NE.0) THEN
+	      IF (INDEX('CURRENT',INPUT(:DELIM-1)).EQ.1) THEN
+		 SVAL = BULL_POINT
+		 IER = 0
+	      END IF
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      ILEN = ILEN - DELIM
+	      DECODE(ILEN,'(I<ILEN>)',INPUT(DELIM+1:),IOSTAT=IER) EVAL
+	      IF (IER.NE.0) THEN
+	         IF (INDEX('LAST',INPUT(DELIM+1:TRIM(INPUT))).EQ.1) THEN
+		    EVAL = F_NBULL
+		    IER = 0
+                 ELSE IF (INDEX('CURRENT',
+     &                  INPUT(DELIM+1:TRIM(INPUT))).EQ.1) THEN
+                    EVAL = BULL_POINT
+                    IER = 0
+                 END IF
+ 	      END IF
+	   END IF
+	   IF (EVAL.LT.SVAL) IER = 2
+	END IF
+
+	RETURN
+	END
+
+ 
+
+	SUBROUTINE DIRECTORY(DIR_COUNT)
+C
+C  SUBROUTINE DIRECTORY
+C
+C  FUNCTION: Display directory of messages.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	DATA SCRATCH_D1/0/
+	DATA EXCLUDE_D1/0/
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /CLOSE_FILES_INFO/ CLOSED_FILES
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /POST/ POSTTIME
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /NEW_DIR/ NEW
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /DIRMODE/ DIRMODE
+	DATA DIRMODE/.FALSE./
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED,CLI$_PRESENT,CLOSE_FILES
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER DATETIME*24,SEARCH_STRING*80,OUTLINE*80
+        CHARACTER GROUP*80,STAT*4
+
+	INTEGER TODAY(2)
+
+	CHARACTER*12 EXPIRES,DIR_TYPE
+
+        INTEGER TIMADR(2)                       ! Buffer containing time
+
+	DATA WAITEFN /0/
+
+	NEXT = .TRUE.
+	DIRMODE = .TRUE.
+
+	CALL INIT_QUEUE(SCRATCH_F1,GROUP)
+
+	IF (WAITEFN.EQ.0) CALL LIB$GET_EF(WAITEFN)
+        IER=SYS$BINTIM('0 00:00:05.00',TIMADR)
+   
+	KILL = BTEST(BULL_USER_CUSTOM,1).AND.BTEST(BULL_USER_CUSTOM,3)
+	IF (KILL) IER1 = 0
+
+	FOUND = 0
+	OUT = 6
+
+	CONT = .FALSE.
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   CONT = CLI$PRESENT('CONTINUE')
+	ELSE IF (INCMD(:3).EQ.'   '.AND.NFOLDER.LT.0) THEN
+	   CONT = .TRUE.
+	END IF
+	IF (CONT) THEN
+	   CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+	   SUBJECT = SUBJECT1
+	   REPLY = REPLY1
+	   SEARCH = SEARCH1
+	   FROM_SEARCH = FROM_SEARCH1
+	   SINCE = SINCE1
+	   NEW = NEW1
+           ANY_SEARCH = SUBJECT.OR.REPLY.OR.SEARCH.OR.FROM_SEARCH
+	   IF (.NOT.ANY_SEARCH) THEN 
+	      WRITE (6,'('' ERROR: No previous search to continue.'')')
+	      RETURN
+	   END IF
+	   INCMD = ' '
+	   LEN_P = 0
+	   DIR_COUNT = DIR_COUNT1
+	   NFOLDER = NFOLDER1
+	   I = DIR_COUNT
+	   IF (DIR_COUNT.EQ.-1) THEN 
+	      I = SBULL - 1
+	   END IF
+	   GO TO 200
+	END IF
+	NFOLDER = 0
+
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   IF (CLI$GET_VALUE('OUTPUT',BULL_PARAMETER,LEN_P)) THEN
+	      OPEN(UNIT=3,FILE=BULL_PARAMETER(:LEN_P),IOSTAT=IER,
+     &		DEFAULTFILE='.LIS',
+     &	        RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      IF (IER.NE.0) THEN
+	         WRITE(6,1000) BULL_PARAMETER(:LEN_P)
+		 RETURN
+	      END IF
+	      OUT = 3
+	      INQUIRE (UNIT=3,NAME=BULL_PARAMETER)
+	      WRITE (6,1040) BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+	   ELSE
+	      CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+	   END IF
+	   IF (.NOT.CLI$PRESENT('SELECT_FOLDER')) THEN
+	      IF (CLI$PRESENT('MARKED')) THEN
+		 READ_TAG = 1 + IBSET(0,1)
+	      ELSE IF (CLI$PRESENT('SEEN')) THEN
+		 READ_TAG = 1 + IBSET(0,2)
+	      ELSE IF (CLI$PRESENT('UNMARKED')) THEN
+		 READ_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+	      ELSE IF (CLI$PRESENT('UNSEEN')) THEN
+		 READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+	      ELSE IF (CLI$PRESENT('ALL')) THEN
+		 READ_TAG = IBSET(0,1) + IBSET(0,2)
+		 IF (REMOTE_SET.GE.3) THEN
+		    BULL_POINT = F_START - 1
+		 ELSE
+		    BULL_POINT = 0
+		 END IF
+ 	      END IF
+	      IF (READ_TAG) THEN
+	         IF (.NOT.(FOLDER_NUMBER.GE.0.OR.REMOTE_SET.GE.3)) THEN
+		    WRITE (6,'('' ERROR: Invalid qualifier'',
+     &			       '' with remote folder.'')')
+		    READ_TAG = IBSET(0,1) + IBSET(0,2)
+		    GO TO 9999
+		 END IF
+		 CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,BULL_POINT)
+	      END IF
+	   END IF
+	   SUBJECT = CLI$PRESENT('SUBJECT').OR.CLI$PRESENT('NOREPLIES')
+	   REPLY = CLI$PRESENT('REPLY')
+           REPLY_FIRST = REPLY
+	   SEARCH = CLI$PRESENT('SEARCH')
+	   FROM_SEARCH = CLI$PRESENT('FROM')
+           ANY_SEARCH = SUBJECT.OR.REPLY.OR.SEARCH.OR.FROM_SEARCH
+	   EXTRACTING = CLI$PRESENT('EXTRACT')
+	   DELETING = CLI$PRESENT('DELETE')
+	   UNDELETING = CLI$PRESENT('UNDELETE')
+	   IF (DELETING.OR.UNDELETING) THEN
+	      OLDPAGING = PAGING
+	      PAGING = .FALSE.
+	   END IF
+	   PRINTING = CLI$PRESENT('PRINT')
+	   POSTTIME = CLI$PRESENT('POST')
+	   NEW = CLI$PRESENT('NEW')
+	   NEGATED = CLI$PRESENT('NEGATED')
+	   IF (SEARCH) THEN
+	      IER1 = CLI$GET_VALUE('SEARCH',SEARCH_STRING,SLEN)
+	   ELSE IF (SUBJECT) THEN
+	      IER1 = CLI$GET_VALUE('SUBJECT',SEARCH_STRING,SLEN)
+           ELSE IF (FROM_SEARCH) THEN
+              IER1 = CLI$GET_VALUE('FROM',SEARCH_STRING,SLEN)
+	   ELSE IF (REPLY) THEN
+	      SEARCH_STRING = ' '
+	   ELSE IF (CLI$PRESENT('NOREPLIES')) THEN
+	      SEARCH_STRING = 'RE:'
+	      SLEN = 3
+              NEGATED = .TRUE.
+	   END IF
+
+	   MATCH_MODE = 0
+	   IF (CLI$PRESENT('MATCH')) THEN
+	      CALL CLI$GET_VALUE('MATCH',BULL_PARAMETER,LEN_P)
+	      IF (BULL_PARAMETER(:LEN_P).EQ.'AND') MATCH_MODE = 1
+	      IF (BULL_PARAMETER(:LEN_P).EQ.'XOR') MATCH_MODE = 2
+	   END IF
+	ELSE
+	   CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+	   EXTRACTING = .FALSE.
+	   PRINTING = .FALSE.
+	   POSTTIME = .TRUE.
+	   DELETING = .FALSE.
+	   UNDELETING = .FALSE.
+	   IF (INCMD(:3).EQ.'IND') THEN
+	      SUBJECT = .FALSE.
+	      REPLY = .FALSE.
+              REPLY_FIRST = .FALSE.
+	      SEARCH = .FALSE.
+	      FROM_SEARCH = .FALSE.
+              ANY_SEARCH = .FALSE.
+	   ELSE
+	      NEW = .FALSE.
+	   END IF
+	END IF
+	OUTPUT = EXTRACTING.OR.PRINTING
+
+	START = .FALSE.
+	SINCE = .FALSE.
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   IF (CLI$PRESENT('GROUP')) THEN
+	      CALL INIT_QUEUE(SCRATCH_F1,GROUP)
+	      SCRATCH_F = SCRATCH_F1
+	      NGROUP = 0
+	      DO WHILE (CLI$GET_VALUE('GROUP',GROUP)
+     &	       .NE.%LOC(CLI$_ABSENT))	   	   ! Get the specified folders
+	         NGROUP = NGROUP + 1
+	         CALL LOWERCASE(GROUP)
+	         CALL WRITE_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	      END DO
+	      SCRATCH_F = SCRATCH_F1
+	      CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	      GLEN = TRIM(GROUP)
+	      FEEDBACK = CLI$PRESENT('FEEDBACK')
+	      NFOLDER = -1000
+	      NFOLDER1 = -1000
+	      SUBJECT1 = SUBJECT
+	      REPLY1 = REPLY
+	      SEARCH1 = SEARCH
+	      FROM_SEARCH1 = FROM_SEARCH
+	      I = SBULL - 1
+	      SINCE = CLI$PRESENT('SINCE')
+	      IF (SINCE) IER = CLI$GET_VALUE('SINCE',DATETIME)
+	      SINCE1 = SINCE
+	      NEW1 = NEW
+	      GOTO 200
+	   END IF
+	END IF
+
+C
+C  Directory listing is first buffered into temporary memory storage before
+C  being outputted to the terminal.  This is to be able to quickly close the
+C  directory file, and to avoid the possibility of the user holding the screen,
+C  and thus causing the directory file to stay open.  The temporary memory
+C  is structured as a linked-list queue, where SCRATCH_D1 points to the header
+C  of the queue.  See BULLSUBS.FOR for more description of the queue.
+C
+
+	CALL INIT_QUEUE(SCRATCH_D1,BULLDIR_ENTRY)
+	SCRATCH_D = SCRATCH_D1
+	CALL INIT_QUEUE(EXCLUDE_D1,%DESCR(I))
+	EXCLUDE_D = EXCLUDE_D1
+	NEXCLUDE = 0
+
+	CALL OPEN_BULLDIR_SHARED		! Get directory file
+
+	CALL READDIR(0,IER)			! Does directory header exist?
+	NEWDIR = .FALSE.
+	IF (IER.EQ.1.AND.NBULL.GT.0) THEN	! And are there messages?
+	   IF (DIR_COUNT.EQ.0) THEN
+	      NEWDIR = .TRUE.
+	      EXPIRATION = CLI$PRESENT('EXPIRATION')
+	      IF (CLI$PRESENT('START')) THEN	! Start number specified?
+		 START = .TRUE.
+	         IER = CLI$GET_VALUE('START',BULL_PARAMETER,LEN_P)
+	         DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) DIR_COUNT
+		 IF (DIR_COUNT.LT.1) THEN
+		    WRITE (6,'('' ERROR: Invalid starting message.'')')
+		    CALL CLOSE_BULLDIR
+		    DIR_COUNT = 0
+		    GO TO 9999
+		 END IF
+	      ELSE IF (CLI$PRESENT('SINCE').OR.NEW) THEN
+		 SINCE = CLI$PRESENT('SINCE')
+	         IF (SINCE) IER = CLI$GET_VALUE('SINCE',DATETIME)
+		 CALL GET_NEW_OR_SINCE(NEW,SINCE,IER,DATETIME)
+		 IF (NEW.AND.IER.EQ.0) THEN	! was /NEW specified?
+		    IF (REMOTE_SET.LT.3) THEN
+		       WRITE (6,'('' No new messages are present in'',
+     &			'' folder '',A,''.'')') FOLDER(:TRIM(FOLDER))
+		       CALL CLOSE_BULLDIR
+		       GO TO 9999
+		    ELSE
+		       WRITE (6,'('' No new messages are present in'',
+     &			 '' folder '',A,''.'')')
+     &			 FOLDER_NAME(:TRIM(FOLDER_NAME))
+		       CALL CLOSE_BULLDIR
+		       GO TO 9999
+		    END IF
+		 END IF
+
+		 IF (IER.EQ.0) THEN
+		    WRITE (6,'('' No messages past specified date.'')')
+		    CALL CLOSE_BULLDIR
+		    GO TO 9999
+		 ELSE
+		    DIR_COUNT = IER
+		 END IF
+	      ELSE
+	         DIR_COUNT = BULL_POINT
+		 IF (DIR_COUNT.EQ.0) DIR_COUNT = 1
+	      END IF
+
+	      IER1 = 0
+
+	      IF (READ_TAG) THEN
+	         IF (SUBJECT.OR.REPLY.OR.SEARCH.OR.FROM_SEARCH) THEN
+		    WRITE (6,'('' ERROR: Qualifier not valid when '',
+     &			''displaying only tagged messages.'')')
+	            SUBJECT = .FALSE.
+	            REPLY = .FALSE.
+	      	    SEARCH = .FALSE.
+	      	    FROM_SEARCH = .FALSE.
+	      	    ANY_SEARCH = .FALSE.
+		    CALL CLOSE_BULLDIR
+		    GO TO 9999
+		 END IF
+	         IF (.NOT.(SINCE.OR.NEW.OR.START)) THEN
+	            DIR_COUNT = 1
+		 END IF
+		 CALL READDIR(DIR_COUNT,IER1)
+		 IF (IER1.EQ.DIR_COUNT+1) IER1 = 0
+		 IF (REMOTE_SET.GE.3.OR.BTEST(READ_TAG,3)) THEN
+		    MSG_NUM = DIR_COUNT-1
+		 ELSE
+		    CALL DECREMENT_MSG_KEY
+	         END IF
+	      END IF
+
+	      IF (START.AND.DIR_COUNT.GT.NBULL) THEN
+	         IF (READ_TAG) THEN
+		    SBULL = NBULL + 1
+		    GO TO 100
+		 ELSE
+		    START = .FALSE.
+		    DIR_COUNT = NBULL
+		 END IF
+	      END IF
+	      IF (SINCE.OR.NEW.OR.START) THEN
+		 SBULL = DIR_COUNT
+	         EBULL = DIR_COUNT + (PAGE_LENGTH - 7) - 1
+	         IF (EBULL.GE.NBULL-2) EBULL = NBULL
+	      ELSE
+		 DIFF = 1
+	         IF (REMOTE_SET.LT.3.AND.DIR_COUNT.NE.NBULL) THEN
+		    CALL READDIR(DIR_COUNT,IER)
+	   	    DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,
+     &			       FOLDER_NUMBER+1),MSG_BTIM)
+	            IF (LAST_READ_BTIM(1,FOLDER_NUMBER+1).EQ.MSG_BTIM(1)
+     &		   .AND.LAST_READ_BTIM(2,FOLDER_NUMBER+1).EQ.MSG_BTIM(2))
+     &			DIFF = 0
+		    IF (READ_TAG) CALL DECREMENT_MSG_KEY
+	         ELSE IF (DIR_COUNT.NE.F_NBULL) THEN
+		    CALL NEWS_GET_NEWEST_MESSAGE(DIFF)
+		    IF (DIFF.NE.0) THEN
+		       DIFF = DIFF - DIR_COUNT - 1
+	            ELSE
+	               DIFF = 1
+	            END IF
+                 END IF
+	         IF (DIFF.GT.0.AND.
+     &		     NBULL-DIR_COUNT+1.LE.PAGE_LENGTH-5) THEN
+	            EBULL = NBULL
+	            SBULL = NBULL - (PAGE_LENGTH-5) + 1
+	            IF (SBULL.LT.1) SBULL = 1
+	         ELSE
+	            SBULL = DIR_COUNT
+	            EBULL = DIR_COUNT + (PAGE_LENGTH - 7) - 1
+	            IF (EBULL.GE.NBULL-2) EBULL = NBULL
+	         END IF
+	      END IF
+
+	      IER1 = 0
+	      IF (REMOTE_SET.LT.3) F_START = 1
+	      IF (DIR_COUNT.GT.F_START.AND.KILL.AND..NOT.(ANY_SEARCH.OR.START
+     &		 .OR.SINCE.OR.NEW).AND.NEWDIR.AND..NOT.READ_TAG) THEN
+       	         IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	         I = DIR_COUNT
+		 NUM = 0
+	         SBULL = DIR_COUNT
+	 	 DO WHILE (NUM.LT.PAGE_LENGTH-5.AND.I.LE.NBULL)
+		    CALL READDIR(I,IER)
+		    IF (I.EQ.NBULL) IER1 = 1
+		    IF (I.EQ.DIR_COUNT.AND.I+1.NE.IER) DIR_COUNT = I + 1
+		    IF (I+1.EQ.IER) THEN 
+		       NUM = NUM + 1
+	               IF (BTEST(SYSTEM,8)) THEN
+	                  CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		          NEXCLUDE = NEXCLUDE + 1
+		       END IF
+		    ELSE
+	               CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(I))
+		       NEXCLUDE = NEXCLUDE + 1
+		    END IF
+		    I = I + 1
+		 END DO
+		 IF (IER1.EQ.0.AND.NUM.GT.PAGE_LENGTH-7) NUM = PAGE_LENGTH - 7
+	         IF (IER1.NE.0.AND.NUM.LT.PAGE_LENGTH-5.AND.
+     &				SBULL.GT.F_START) THEN
+	            I = SBULL - 1
+		    NEXT = .FALSE.
+	 	    DO WHILE (NUM.LT.PAGE_LENGTH-5.AND.I.GE.F_START)
+		       CALL READDIR(I,IER)
+		       IF (I.EQ.NBULL) IER1 = 1
+		       IF (I+1.EQ.IER) THEN
+			  NUM = NUM + 1
+		          DIR_COUNT = I
+	                  IF (BTEST(SYSTEM,8)) THEN
+	                     CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		             NEXCLUDE = NEXCLUDE + 1
+		          END IF
+		       ELSE
+	                  CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &					%DESCR(I))
+		          NEXCLUDE = NEXCLUDE + 1
+		       END IF
+		       I = I - 1
+		    END DO
+		    NEXT = .TRUE.
+	         END IF
+	         SBULL = DIR_COUNT
+	         EBULL = SBULL + NUM - 1
+	      END IF
+	   ELSE IF (DIR_COUNT.EQ.-1.AND..NOT.READ_TAG) THEN
+	      SUBJECT = .FALSE.
+	      REPLY = .FALSE.
+              SEARCH = .FALSE.
+              FROM_SEARCH = .FALSE.
+	      SBULL = (SBULL - 1) - ((PAGE_LENGTH - 7) - 1)
+	      IF (SBULL.LT.1) SBULL = 1
+	      EBULL = SBULL + (PAGE_LENGTH - 7) - 1
+	      IF (NBULL-SBULL+1.LE.PAGE_LENGTH-5) THEN
+	         SBULL = NBULL - (PAGE_LENGTH-5) + 1
+	         EBULL = NBULL
+	         IF (SBULL.LT.1) SBULL = 1
+	      END IF
+	      IF ((REMOTE_SET.EQ.4.OR.KILL).AND.SBULL.GT.F_START) THEN
+	         NUM = EBULL - SBULL + 1
+	         I = EBULL
+	         NEXT = .FALSE.
+		 NUM1 = 0
+		 EBULL = 0
+	 	 DO WHILE (NUM.GT.0.AND.I.GE.F_START)
+		    CALL READDIR(I,IER)
+		    IF (I.EQ.NBULL) IER1 = 1
+		    IF (I+1.EQ.IER) THEN
+		       IF (EBULL.EQ.0) EBULL = I
+		       NUM = NUM - 1
+		       NUM1 = NUM1 + 1
+		       SBULL = I
+	               IF (BTEST(SYSTEM,8)) THEN
+	                  CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		          NEXCLUDE = NEXCLUDE + 1
+		       END IF
+		    ELSE
+	               CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(I))
+		       NEXCLUDE = NEXCLUDE + 1
+	            END IF
+		    IF (NUM.GT.0) I = I - 1
+		 END DO
+       	         IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	         NEXT = .TRUE.
+		 NUM = NUM1
+	         IF (NUM.LE.PAGE_LENGTH-7) THEN
+	            IF (IER1.EQ.0.AND.I.LE.F_START) THEN
+		       I = EBULL
+	               DO WHILE (I.LT.NBULL.AND.NUM.LE.PAGE_LENGTH-5)
+	                  I = I + 1
+	                  CALL READDIR(I,IER)
+			  IF (I+1.EQ.IER) THEN
+			     NUM = NUM + 1 
+	               	     IF (BTEST(SYSTEM,8)) THEN
+	                        CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		                NEXCLUDE = NEXCLUDE + 1
+		             END IF
+			  ELSE
+	                     CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(I))
+		             NEXCLUDE = NEXCLUDE + 1
+		          END IF
+	               END DO
+	               IF (NUM.GT.PAGE_LENGTH-5) NUM = PAGE_LENGTH-7
+                    ELSE IF (IER1.NE.0.AND.I.GT.F_START) THEN
+		       I = F_START - 1
+		       J = 0
+	               DO WHILE (J.LT.3.AND.I.LT.NBULL)
+	                  I = I + 1
+	                  CALL READDIR(I,IER)
+			  IF (I+1.EQ.IER) THEN
+			     J = J + 1
+	                     IF (BTEST(SYSTEM,8)) THEN
+	                        CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		                NEXCLUDE = NEXCLUDE + 1
+		             END IF
+			  ELSE
+	                     CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(I))
+		             NEXCLUDE = NEXCLUDE + 1
+		          END IF
+	               END DO
+	               IF (MSG_NUM.GE.SBULL) THEN 
+			  NUM = NUM + 2 
+	                  SBULL = F_START
+	               END IF
+	            END IF
+	         END IF
+	         EBULL = SBULL + NUM - 1
+	      END IF
+	   ELSE IF (DIR_COUNT.EQ.-1.AND.READ_TAG) THEN
+100	      CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,FIRST_BULL)
+	      FIRST_BULL = FIRST_BULL + 1
+	      DIR_COUNT = FIRST_BULL
+	      IER1 = IER
+	      IER = 0
+	      FBULL = 0
+	      EBULL = 0
+	      LBULL = SBULL.GT.NBULL
+	      DO WHILE (SBULL.GT.FIRST_BULL.AND.IER.EQ.0)
+		 SBULL = SBULL - 1
+	         CALL READDIR(SBULL,IER)
+		 IF (IER.EQ.SBULL+1) THEN
+	            CALL GET_THIS_TAG(FOLDER_NUMBER,IER,DIR_COUNT,DUMMY)
+		    IF (IER.EQ.0) THEN
+		       IF (FBULL.EQ.0) EBULL = DIR_COUNT
+		       FBULL = FBULL +1
+		       IF ((.NOT.LBULL.AND.FBULL.EQ.PAGE_LENGTH-7).OR.
+     &			   (LBULL.AND.FBULL.EQ.PAGE_LENGTH-5)) THEN
+		          IER = 1
+		       END IF
+		    ELSE
+		       IER = 0
+		    END IF
+		 ELSE
+		    IER = 1
+		 END IF
+	      END DO
+	      IF (DIR_COUNT.EQ.FIRST_BULL.AND..NOT.LBULL) THEN
+		 CALL READDIR(EBULL,IER)
+		 IER = 0
+		 DO WHILE (IER.EQ.0.AND.FBULL.LT.PAGE_LENGTH-7)
+		    CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DIR_COUNT,DUMMY)
+		    IF (IER.EQ.0) THEN
+		       FBULL = FBULL + 1
+		       EBULL = DIR_COUNT
+		    END IF
+		 END DO
+		 DO I=1,3
+		    CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DIR_COUNT,DUMMY)
+		 END DO
+		 IF (IER.NE.0) THEN
+		    EBULL = DIR_COUNT
+		    FBULL = FBULL + 2
+	         END IF
+	      END IF
+	      CALL READDIR(EBULL,IER)
+	      IF (EBULL+1.NE.IER) THEN
+		 EBULL = EBULL + 1
+	      ELSE
+	         CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DUMMY,DUMMY1)
+		 IF (IER.NE.0) EBULL = EBULL + 1
+	      END IF
+	      CALL READDIR(SBULL,IER)
+	      IF (REMOTE_SET.GE.3.OR.BTEST(READ_TAG,3)) THEN
+		 MSG_NUM = MSG_NUM-1
+	      ELSE
+		 CALL DECREMENT_MSG_KEY
+	      END IF
+	      EBULL = SBULL + FBULL - 1
+	   ELSE
+	      SBULL = DIR_COUNT
+	      EBULL = DIR_COUNT + (PAGE_LENGTH - 7) - 1
+	      IF (EBULL.GE.NBULL-2) EBULL = NBULL
+	   END IF
+	   IF (.NOT.PAGING.OR.OUTPUT.OR.OUT.EQ.3) EBULL = NBULL
+	   IF (INCMD(:3).EQ.'DIR') THEN
+	      IF (CLI$GET_VALUE('END',BULL_PARAMETER,LEN_P)) THEN
+	         DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) EBULL
+	         EBULL = MIN(EBULL,NBULL)
+	      END IF
+	   END IF
+	   IF (ANY_SEARCH) THEN
+       	      IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	   ELSE IF ((.NOT.REMOTE_SET.OR.KILL).AND..NOT.READ_TAG) THEN
+       	      IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	      EXCLUDE_D = EXCLUDE_D1
+	      SEXC = NBULL + 1
+	      LEXC = 0
+	      DO I=1,NEXCLUDE
+	         CALL READ_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(J))
+		 IF (J.LT.SEXC) SEXC = J
+		 IF (J.GT.LEXC) LEXC = J
+	      END DO
+	      I1 = SBULL
+	      I = SBULL
+	      DO WHILE (I.LE.EBULL)
+	         EXCLUDE_D = EXCLUDE_D1
+		 J = 0
+		 IER = I1
+		 IF (I1.GE.SEXC.AND.I1.LE.LEXC) THEN 
+		    N = NEXCLUDE
+		    DO WHILE (N.GT.0.AND.J.EQ.0)
+	               CALL READ_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(J))
+		       N = N - 1
+		       IF (J.NE.I1.AND.J.NE.-I1) J = 0
+		    END DO
+	            IF (J.LE.0) THEN 
+	               BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,1)
+		       CALL READDIR(I1,IER)
+	               BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+		       IF (J.LT.0) SYSTEM = IBSET(SYSTEM,8)
+		    END IF
+	         ELSE
+	            CALL READDIR(I1,IER)
+		 END IF
+		 IF (KILL.AND.I1.EQ.NBULL) IER1 = 1
+		 IF (IER.EQ.I1+1) THEN
+	            CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,
+     &					BULLDIR_ENTRY)
+		    I = I + 1
+	         ELSE IF (I1.GE.NBULL) THEN
+		    EBULL = I - 1
+	         END IF
+	         I1 = I1 + 1
+	      END DO
+	   ELSE IF (READ_TAG) THEN
+	      I = 0
+	      DO WHILE (I.LE.EBULL.AND.IER1.EQ.0)
+		 CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,DIR_COUNT,TAG_TYPE)
+		 IF (I.EQ.0.AND.IER1.EQ.0) THEN
+		    EBULL = EBULL - SBULL + DIR_COUNT
+		    SBULL = DIR_COUNT
+		    I = SBULL
+		 END IF
+	 	 SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+	         CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+		 I = I + 1
+	      END DO
+	      EBULL = I - 1
+	      IF (IER1.NE.0) THEN
+	         EBULL = EBULL - 1
+	      ELSE
+	         CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,DUMMY,TAG_TYPE)
+		 IF (IER1.EQ.0) THEN
+		    IER = 0
+		    EBULL_SAVE = EBULL
+		    DO I=1,2
+		       IF (IER.EQ.0) THEN
+			  SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+	                  CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,
+     &							BULLDIR_ENTRY)
+			  EBULL = EBULL + 1
+	                  CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DUMMY,
+     &				TAG_TYPE)
+		       END IF
+		    END DO
+		    IF (IER.NE.0) THEN
+	               CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,FIRST_BULL)
+	               IF (SBULL.NE.FIRST_BULL+1) EBULL = EBULL_SAVE
+		       IER1 = 1
+		    ELSE
+		       EBULL = EBULL_SAVE
+		    END IF
+		 END IF
+	      END IF
+	   ELSE
+	      CALL REMOTE_DIRECTORY_COMMAND
+     &				     (SBULL,EBULL,.FALSE.,SCRATCH_D,IER)
+	      IF (IER.NE.0) THEN
+	         CALL CLOSE_BULLDIR
+		 CALL DISCONNECT_REMOTE
+		 GO TO 9999
+	      END IF
+	   END IF
+	ELSE
+	   NBULL = 0
+	END IF
+
+	IF (NBULL.EQ.0.OR.EBULL.LT.SBULL) THEN
+	   CALL CLOSE_BULLDIR			! We don't need file anymore
+	   IF (READ_TAG) THEN
+	      IF (BTEST(READ_TAG,1).AND.BTEST(READ_TAG,3)) THEN
+		 DIR_TYPE = 'unmarked'
+	      ELSE IF (BTEST(READ_TAG,2).AND.BTEST(READ_TAG,3)) THEN
+		 DIR_TYPE = 'unseen'
+	      ELSE IF (BTEST(READ_TAG,1)) THEN
+		 DIR_TYPE = 'marked'
+	      ELSE IF (BTEST(READ_TAG,2)) THEN
+		 DIR_TYPE = 'seen'
+	      END IF
+	      WRITE (6,'('' No '',A,'' messages are present in'',
+     &		     '' folder '',A,''.'')')
+     &		DIR_TYPE(:TRIM(DIR_TYPE)),FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   ELSE
+	      IF (INCMD(:3).EQ.'DIR'.AND.ANY_SEARCH) THEN
+	         IF (.NOT.CLI$PRESENT('START').AND..NOT.CONT) THEN
+	             WRITE (6,'('' No matches found starting search'',
+     &			'' from message number '',I)') SBULL
+		    DIR_COUNT = -1
+		    GO TO 9999
+	         END IF
+	      END IF
+	      WRITE (6,'('' There are no messages present.'')')
+	   END IF
+	   DIR_COUNT = -1
+	   GO TO 9999
+	END IF
+
+C
+C  Directory entries are now in queue.  Output queue entries to screen.
+C
+
+	IF (NFOLDER.EQ.0) CALL DIRECTORY_HEADER
+     &		(OUTLINE,PRINTING,EXTRACTING,EXPIRATION,OUT,
+     &	         DELETING,UNDELETING)
+
+	TAG = (BULL_TAG.AND.(REMOTE_SET.EQ.0.OR.REMOTE_SET.EQ.1)).OR.
+     &			(BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)
+
+	IF (.NOT.ANY_SEARCH.AND.TAG.AND..NOT.READ_TAG) THEN
+	   IF (INCMD(:3).NE.'   ') THEN
+	      SCRATCH_D = SCRATCH_D1		! Init queue pointer to header
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+	      CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,TAG_TYPE)
+	      IF (IER.NE.0) NEXT_TAG = NBULL + 1
+	   END IF
+	   SCRATCH_D = SCRATCH_D1		! Init queue pointer to header
+	   DO I=SBULL,EBULL
+	      SAVE_SCRATCH_D = SCRATCH_D
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+	      IF (TAG.AND.MSG_NUM.EQ.NEXT_TAG) THEN
+		 SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+	         CALL WRITE_QUEUE(%VAL(SAVE_SCRATCH_D),DUMMY,BULLDIR_ENTRY)
+	         CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,TAG_TYPE)
+	         IF (IER.NE.0) NEXT_TAG = NBULL + 1
+	      END IF
+	   END DO
+	END IF
+
+	CALL CLOSE_BULLDIR			! We don't need file anymore
+
+	SCRATCH_D = SCRATCH_D1			! Init queue pointer to header
+
+	I = SBULL
+	START_SEARCH = I
+	IF (.NOT.REPLY_FIRST) THEN
+	   START_SEARCH = I - 1
+	ELSE IF (.NOT.CLI$PRESENT('START')) THEN
+	   START_SEARCH = BULL_POINT
+	END IF
+200	CLOSED = .FALSE.
+	IF (ANY_SEARCH.OR.OUTPUT) THEN
+	   NUM = 0
+	   IF (NFOLDER.NE.-1000) THEN
+	      CLOSED = .TRUE.
+	      CALL OPEN_BULLDIR_SHARED
+	      IF (SEARCH.OR.OUTPUT) CALL OPEN_BULLFIL_SHARED
+	   END IF
+	   CLOSED_FILES = .FALSE.
+	   SEARCH_NUM = 1
+	   REVERSE = .FALSE.
+	END IF
+	DO WHILE (I.LE.EBULL.AND.FOUND.GT.-3)
+	   IF (.NOT.ANY_SEARCH) THEN
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+	   ELSE
+ 	      IF (NFOLDER.NE.-1000.AND.I.GE.SBULL)
+     &		 CALL GET_SEARCH(FOUND,SEARCH_STRING,SEARCH_NUM,SLEN,0,
+     &		    START_SEARCH,REVERSE,SUBJECT,REPLY_FIRST,.FALSE.,
+     &		    .TRUE.,FROM_SEARCH,NEGATED,.FALSE.)
+	      IF (INCMD(:3).NE.'   '.AND.TAG.AND.FOUND.GT.0) THEN
+	         CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,
+     &		    TAG_TYPE)
+	         IF (IER.NE.0) NEXT_TAG = NBULL + 1
+		 NEXT = .FALSE.
+		 CALL READDIR(FOUND,IER)
+		 NEXT = .TRUE.
+	      END IF
+	      REPLY_FIRST = .FALSE.
+	      IF (FOUND.GT.0) THEN
+		 IF (NFOLDER.LT.0.AND.(I.EQ.F_START.OR.I.EQ.DIR_COUNT)) THEN
+	   	    IF (FEEDBACK) CALL LIB$ERASE_PAGE(1,1)
+		    CALL DIRECTORY_HEADER
+     &			(OUTLINE,PRINTING,EXTRACTING,EXPIRATION,OUT,
+     &			 DELETING,UNDELETING)
+		    DIR_COUNT = 0
+		    BULL_POINT = MSG_NUM - 1
+	   	    PRINT_HEADER = .TRUE.
+		 END IF
+		 SEARCH_STRING = ' '
+		 START_SEARCH = FOUND
+	         IF (TAG.AND.MSG_NUM.EQ.NEXT_TAG) THEN
+	            CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,DUMMY)
+	            IF (IER.NE.0) NEXT_TAG = NBULL + 1
+		    NEXT = .FALSE.
+		    CALL READDIR(FOUND,IER)
+		    NEXT = .TRUE.
+		    SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+		    TAG_TYPE = DUMMY
+	         END IF
+		 IF (NFOLDER.LT.0.AND..NOT.OUTPUT) THEN 
+	            NUM = NUM + 1
+	 	    IF (NUM.EQ.PAGE_LENGTH-6) I = EBULL + 1
+		 END IF
+	      ELSE IF (NFOLDER.LT.0.AND.(OUTPUT.OR.I.LE.SBULL)) THEN
+		 IF (CLOSED) THEN
+		    IF (SEARCH.OR.OUTPUT) CALL CLOSE_BULLFIL
+		    CALL CLOSE_BULLDIR
+		    CLOSED = .FALSE.
+		 END IF
+		 GFOUND = .FALSE.
+	       	 CALL DECLARE_CTRLC_AST
+		 DO WHILE (.NOT.GFOUND.AND.NGROUP.GT.0.AND.FLAG.NE.1)
+	            CALL OPEN_BULLNEWS_SHARED
+		    CALL READ_FOLDER_FILE_KEYNUM_TEMP(-NFOLDER,IER)
+		    IF (IER.EQ.0) 
+     &		       CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+		    DO WHILE (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10))
+		       CALL READ_FOLDER_FILE_TEMP(IER)
+	            END DO
+		    IF (IER.NE.0) NFOLDER = 0
+		    DO WHILE (.NOT.GFOUND.AND.NFOLDER.NE.0.AND.FLAG.NE.1)
+	               CALL GET_NEXT_GROUP(.TRUE.,GROUP,GLEN,GFOUND,
+     &				        .FALSE.,STAT,IER,.TRUE.)
+		       CALL CLOSE_BULLFOLDER
+		       IF (GFOUND) THEN
+	      	          START_BULL = 0
+		          OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	                  FOLDER_NUMBER = -1
+		          FOLDER1 = FOLDER1_DESCRIP(
+     &		          		:INDEX(FOLDER1_DESCRIP,' '))
+	                  IF (F1_START.GT.0.AND.F1_START.LE.F1_NBULL) THEN
+			     CALL SELECT_FOLDER(.FALSE.,IER)
+			     START_SEARCH = F_START - 1
+			     IF (IER.AND.(NEW.OR.SINCE)) THEN
+				CALL OPEN_BULLDIR_SHARED
+			        CALL GET_NEW_OR_SINCE(NEW,SINCE,IER1,DATETIME)
+			        CALL CLOSE_BULLDIR
+				IF (IER1.NE.0) THEN
+				   START_SEARCH = IER1 - 1
+				ELSE
+				   IER = 0
+				END IF
+			     END IF
+			  END IF
+		          IF (.NOT.IER.OR.F1_START.EQ.0.OR.
+     &			      F1_START.GT.F1_NBULL) THEN
+		             FOLDER_NUMBER = OLD_FOLDER_NUMBER
+		             CALL OPEN_BULLNEWS_SHARED
+			     CALL READ_FOLDER_FILE_KEYNUM_TEMP(FOLDER1_NUMBER,
+     &								IER)
+		             CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+		             GFOUND = .FALSE.
+			     IF (FLAG.EQ.1) CALL CLOSE_BULLFOLDER
+		          ELSE
+	   	             IF (FEEDBACK) WRITE (6,'('' Searching '',A)')
+     &		          		FOLDER_NAME(:TRIM(FOLDER_NAME))
+		             CHANGE = .TRUE.
+		             NFOLDER = -FOLDER_NUMBER
+			     SBULL = F_START
+			     I = SBULL - 1
+			     EBULL = F_NBULL			     
+		          END IF
+		       ELSE
+		          NFOLDER = 0
+		       END IF
+		    END DO
+		    IF (NFOLDER.EQ.0) NGROUP = NGROUP - 1
+		    IF (NFOLDER.EQ.0.AND.NGROUP.GT.0) THEN
+		       CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+		       GLEN = TRIM(GROUP)
+		       NFOLDER = -1000
+		    ELSE IF (NFOLDER.EQ.0) THEN 
+		       WRITE (6,'('' No messages found.'')')
+		    END IF
+		    IF (NFOLDER.EQ.0) I = EBULL + 1
+ 	            IF (NFOLDER.LT.-1000) THEN 
+		       CALL OPEN_BULLDIR_SHARED
+	               IF (SEARCH.OR.OUTPUT) CALL OPEN_BULLFIL_SHARED
+	               CLOSED = .TRUE.
+	            END IF
+		    NFOLDER1 = NFOLDER
+	         END DO
+		 IF (FLAG.EQ.1) THEN
+		    WRITE (6,'('' Search aborted.'')')
+		    I = EBULL + 1
+		 END IF
+	     	 CALL CANCEL_CTRLC_AST
+	      ELSE
+		 I = EBULL + 1
+	      END IF
+	      IER = SYS$SETIMR(%VAL(WAITEFN),TIMADR,CLOSE_FILES,)
+	   END IF
+	   IF (I.GE.SBULL.AND.I.LE.EBULL.AND.NFOLDER.NE.-1000) THEN
+	      CALL CONVERT_ENTRY_FROMBIN_FOLDER
+	      IF (BTEST(SYSTEM,30)) THEN
+		 OUTLINE  = '>'
+	      ELSE IF (BTEST(SYSTEM,8)) THEN
+		 OUTLINE  = '#'
+	      ELSE
+		 OUTLINE  = ' '
+	      END IF
+	      IF (BTEST(SYSTEM,29)) THEN
+		 OUTLINE(2:)  = '*'
+	      ELSE
+		 OUTLINE(2:)  = ' '
+	      END IF
+	      N = MAX(INT(LOG10(REAL(MSG_NUM)))+1,3)
+	      IF (EXDATE(8:12).LT.'1994'.AND.REMOTE_SET.NE.3) THEN
+	         WRITE(OUTLINE(3:),2010) MSG_NUM,DESCRIP(:54-N),FROM,
+     &							'(DELETED)'
+	      ELSE IF (EXPIRATION) THEN
+	         IF (BTEST(SYSTEM,2)) THEN		! Shutdown bulletin?
+		    EXPIRES = 'Shutdown'
+	         ELSE IF (BTEST(SYSTEM,1)) THEN		! Permanent bulletin?
+		    EXPIRES = 'Permanent'
+	         ELSE IF (EXDATE(8:9).EQ.'18'.AND.REMOTE_SET.EQ.3) THEN
+		    EXPIRES = 'Unknown'
+	         ELSE
+		    EXPIRES = EXDATE(:7)//EXDATE(10:11)
+	         END IF
+	         WRITE(OUTLINE(3:),2010) MSG_NUM,DESCRIP(:54-N),FROM,
+     &						EXPIRES(:9)
+	      ELSE
+	         WRITE(OUTLINE(3:),2010) MSG_NUM,DESCRIP(:54-N),FROM,
+     &						DATE(:7)//DATE(10:11)
+	      END IF
+	      NOTHING = .FALSE.
+	      IF (OUT.EQ.6) THEN 
+	         WRITE(OUT,'(1X,A)') OUTLINE
+	      ELSE
+	         WRITE(OUT,'(A)') OUTLINE
+	      END IF
+	      IF (OUTPUT) THEN
+		 FOUND_MSG = .TRUE.
+		 CALL SYS$SETAST(%VAL(0))
+		 NEXT = .FALSE.
+	         IF (PRINTING) THEN
+	            CALL PRINT(MSG_NUM,CLOSED_FILES)
+	         ELSE
+		    CALL FILE(MSG_NUM,CLOSED_FILES,PRINT_HEADER)
+	   	    PRINT_HEADER = .FALSE.
+		    IF (MSG_NUM.GT.0) THEN
+		       I = EBULL
+	               FOUND = 0
+                    ELSE
+		       MSG_NUM = -MSG_NUM
+	            END IF
+	         END IF
+		 NEXT = .TRUE.
+		 CALL SYS$SETAST(%VAL(1))
+	      END IF
+	      IF (DELETING) THEN
+		 BULL_SAVE = BULL_POINT
+		 BULL_POINT = MSG_NUM
+		 IF (CLOSED) THEN
+		    IF (SEARCH.OR.OUTPUT) CALL CLOSE_BULLFIL
+		    CALL CLOSE_BULLDIR
+		 END IF
+		 CALL DELETE_MSG
+		 IF (CLOSED) THEN
+		    CALL OPEN_BULLDIR_SHARED
+		    IF (SEARCH.OR.OUTPUT) CALL OPEN_BULLFIL_SHARED
+		 END IF
+		 BULL_POINT = BULL_SAVE
+	      ELSE IF (UNDELETING) THEN
+		 BULL_SAVE = BULL_POINT
+		 BULL_POINT = MSG_NUM
+		 IF (CLOSED) THEN
+		    IF (SEARCH.OR.OUTPUT) CALL CLOSE_BULLFIL
+		    CALL CLOSE_BULLDIR
+		 END IF
+		 CALL UNDELETE
+		 IF (CLOSED) THEN
+		    CALL OPEN_BULLDIR_SHARED
+		    IF (SEARCH.OR.OUTPUT) CALL OPEN_BULLFIL_SHARED
+		 END IF
+		 BULL_POINT = BULL_SAVE
+	      END IF
+	   END IF
+	   I = I + 1
+	   IF (ANY_SEARCH) IER = SYS$CANTIM(,)
+	END DO
+
+	DIR_COUNT = MSG_NUM + 1			! Update directory counter
+
+	IF (ANY_SEARCH.OR.OUTPUT) THEN
+	   IF (CLOSED) THEN
+	      IF (SEARCH.OR.OUTPUT) CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	   END IF
+	   IF (ANY_SEARCH) THEN
+	      IF (FOUND.GT.0) THEN
+	         DIR_COUNT = FOUND + 1
+	      ELSE
+	         DIR_COUNT = NBULL + 1
+	      END IF
+	   END IF
+	END IF
+
+	IF (DIR_COUNT.GT.NBULL
+     &		.OR.((READ_TAG.OR.KILL).AND.IER1.NE.0)) THEN
+						! Outputted all entries?
+	   IF (PRINTING) THEN 
+	      IF (CLI$PRESENT('NOW').AND.FOUND_MSG) THEN
+	         INCMD = 'PRINT/NOW'
+	         IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	         CALL PRINT(MSG_NUM,CLOSED_FILES)
+	      END IF
+	   ELSE IF (EXTRACTING.AND.FOUND_MSG) THEN
+	      CALL FILE(0,CLOSED_FILES,.FALSE.)
+	   END IF
+	   IF (NFOLDER.LT.0) THEN 
+	      IF (FLAG.EQ.1) WRITE(6,1020)
+	   ELSE
+	      DIR_COUNT = -1			! Yes. Set counter to -1.
+	   END IF
+	ELSE IF (NFOLDER.NE.0.OR.(-NFOLDER1.EQ.FOLDER_NUMBER.AND.
+     &		   INCMD(:1).EQ.' ')) THEN
+	   IF (FLAG.EQ.1) WRITE(6,1020)
+	ELSE IF (FLAG.NE.1) THEN 
+	   WRITE(6,1010)			! Else say there are more
+	END IF
+
+9999	POSTTIME = .FALSE.
+	NEXT = .FALSE.
+	DIRMODE = .FALSE.
+	IF (NFOLDER.NE.0.OR.-NFOLDER1.EQ.FOLDER_NUMBER) THEN
+	   DIR_COUNT1 = DIR_COUNT
+	   IF (DIR_COUNT1.GT.NBULL) DIR_COUNT1 = -1
+	END IF
+	IF (OUT.EQ.3) CLOSE (UNIT=3)
+	IF (DELETING.OR.UNDELETING) PAGING = OLDPAGING
+	RETURN
+
+1000	FORMAT(' ERROR: Error in opening file ',A,'.')
+1010	FORMAT(1X,/,' Press RETURN for more...',/)
+1020	FORMAT(1X,/,' Press RETURN for more, type SEARCH to read ',
+     &		'these messages.',/)
+1040	FORMAT(' Output being written to ',A,'.')
+
+2010	FORMAT(I<N>,1X,A<54-N>,1X,A12,1X,A9)
+
+	END
+
+
+	SUBROUTINE CLOSE_FILES
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /CLOSE_FILES_INFO/ CLOSED_FILES
+
+	INQUIRE(UNIT=1,OPENED=IER)
+	IF (IER) CALL CLOSE_BULLFIL
+
+	INQUIRE(UNIT=2,OPENED=IER)
+	IF (IER) CALL CLOSE_BULLDIR
+
+	CLOSED_FILES = .TRUE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_MSGKEY(BTIM,MSG_KEY)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER BTIM(2)
+
+	CHARACTER*8 MSG_KEY,INPUT
+
+	CALL LIB$MOVC3(8,BTIM(1),%REF(INPUT))
+
+	DO I=1,8
+	   MSG_KEY(I:I) = INPUT(9-I:9-I)
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE FILE(FILE_NUM,OPEN_IT,PRINT_HEADER)
+C
+C  SUBROUTINE FILE
+C
+C  FUNCTION:  Copies a bulletin to a file.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /READ_DISPLAY/ LINE_OFFSET
+
+	COMMON /FILE_DIRECTORY/ FILE_DIRECTORY
+	CHARACTER*64 FILE_DIRECTORY
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER*128 FILENAME
+
+	DATA OPENED /.FALSE./
+
+	IF (CAPTIVE(1)) THEN
+	   WRITE (6,'('' ERROR: Command invalid from CAPTIVE account.'')')
+	   RETURN
+	END IF
+
+10	IF (FILE_NUM.EQ.0) THEN
+	IF (.NOT.OPEN_IT) THEN
+	   OPENED = .FALSE.
+	   CLOSE (UNIT=3)
+	   RETURN
+	END IF
+	IF (OPENED) THEN
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	   CLOSE (UNIT=3)			! Bulletin copy completed
+	   OPENED = .FALSE.
+	   RETURN
+	END IF
+	IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	   CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+	   IF (EBULL.GT.F_NBULL) EBULL = F_NBULL
+	ELSE IF (CLI$PRESENT('ALL')) THEN
+	   SBULL = 1
+	   EBULL = F_NBULL
+	   IER = 0
+	ELSE IF (BULL_POINT.EQ.0) THEN	! No.  Have we just read a bulletin?
+	   WRITE(6,1010)		! No, then error.
+	   RETURN
+	ELSE
+	   SBULL = BULL_POINT
+	   EBULL = SBULL
+	   IER = 0
+	END IF
+
+	IF (SBULL.LE.0.OR.IER.NE.0.OR.EBULL.LT.SBULL) THEN
+	   WRITE (6,1015)
+	   IF (OPENED) THEN
+	      CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	      CLOSE (UNIT=3)			! Bulletin copy completed
+	      OPENED = .FALSE.
+	   END IF
+	   WRITE (6,'(1X,A)') BULL_PARAMETER(:LEN_P)
+	   RETURN
+	END IF
+	ELSE
+	   SBULL = FILE_NUM
+	   EBULL = SBULL
+	END IF
+
+	IF (.NOT.OPENED) THEN
+	   IER = CLI$GET_VALUE('EXTRACT',FILENAME,LEN_F)
+
+	   IF (.NOT.IER) THEN
+	      FILENAME = FOLDER
+	      DO I=1,LEN(FILENAME)
+	         IF (FILENAME(I:I).EQ.'.') FILENAME(I:I) = '_'
+	      END DO
+	      FILENAME = FILENAME(:TRIM(FILENAME))//'.TXT'
+	      LEN_F = TRIM(FILENAME)
+	   END IF
+
+	   IF (TRIM(FILE_DIRECTORY).GT.0.AND.INDEX(FILENAME,':').EQ.0
+     &	       .AND.INDEX(FILENAME,'[').EQ.0) THEN
+	      FILENAME = FILE_DIRECTORY(:TRIM(FILE_DIRECTORY))//FILENAME
+	      LEN_F = TRIM(FILENAME)
+	   END IF
+
+	   CALL STR$UPCASE(FILENAME,FILENAME)
+
+	   CALL DISABLE_PRIVS
+
+	   IF (CLI$PRESENT('NEW')) THEN
+	      OPEN(UNIT=3,FILE=FILENAME(:LEN_F),ERR=900,
+     &	        RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	   ELSE
+	      OPEN(UNIT=3,FILE=FILENAME(:LEN_F),IOSTAT=IER,
+     &		RECL=LINE_LENGTH,
+     &		STATUS='OLD',CARRIAGECONTROL='LIST',ACCESS='APPEND')
+	      IF (IER.NE.0) THEN
+	         OPEN(UNIT=3,FILE=FILENAME(:LEN_F),ERR=900,
+     &	           RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      ELSE IF (CLI$PRESENT('FF')) THEN
+	         WRITE (3,'(A)') CHAR(12)
+	      END IF
+	   END IF
+
+	   CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+
+	   HEAD = CLI$PRESENT('HEADER')
+
+	   IF (OPEN_IT) THEN
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL OPEN_BULLFIL_SHARED	! Open BULLETIN file
+	   END IF
+	   OPENED = .TRUE.
+	   FIRST = .TRUE.
+	END IF
+
+	IF (PRINT_HEADER) THEN
+	   WRITE (3,'(/,''Newsgroup: '',A)')
+     &		FOLDER_NAME(:TRIM(FOLDER_NAME))
+	END IF
+
+	DO FBULL = SBULL,EBULL
+	   FBULL1 = FBULL
+	   CALL READDIR(FBULL,IER)	! Get info for specified bulletin
+
+	   IF (IER.NE.FBULL+1.OR.FBULL.GT.EBULL.OR.(.NOT.CLI$PRESENT
+     &		('ALL').AND.FBULL1.EQ.SBULL.AND.FBULL.NE.SBULL)) THEN
+	      IF (REMOTE_SET.LT.3.OR.FBULL1.EQ.SBULL) WRITE(6,1030) FBULL1
+	      IF (FBULL1.GT.SBULL) GO TO 100
+	      CLOSE (UNIT=3,STATUS='DELETE')
+	      OPENED = .FALSE.
+	      IF (OPEN_IT) THEN
+	         CALL CLOSE_BULLFIL
+	         CALL CLOSE_BULLDIR
+              END IF
+	      RETURN
+	   ELSE IF (REMOTE_SET) THEN
+	      CALL REMOTE_READ_MESSAGE(FBULL,IER1)
+	      IF (IER1.GT.0) THEN
+	         CALL DISCONNECT_REMOTE
+	      ELSE
+	         CALL GET_REMOTE_MESSAGE(IER1)
+	      END IF
+	      IF (IER1.NE.0) GO TO 100
+	   END IF
+
+	   IF (.NOT.FIRST.AND.CLI$PRESENT('FF')) THEN
+	      WRITE (3,'(A)') CHAR(12)
+	   ELSE IF (FIRST) THEN
+	      FIRST = .FALSE.
+	   END IF
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (HEAD) WRITE(3,1060) INPUT(7:ILEN),DATE//' '//TIME(:8)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE IF (HEAD) THEN
+	      WRITE(3,1060) FROM,DATE//' '//TIME(:8)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      IF (HEAD) WRITE(3,1050) INPUT(7:ILEN)
+	   ELSE
+	      IF (HEAD) WRITE(3,1050) DESCRIP
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END DO
+	END DO
+
+100     IF (FILE_NUM.GT.0) THEN
+	   FILE_NUM = -FILE_NUM
+	   RETURN
+	END IF
+
+	IER = OTS$CVT_L_TI(SBULL,BULL_PARAMETER,,,)
+ 	IF (SBULL.EQ.EBULL) THEN	! Show name of file created.
+	   WRITE(6,1040)
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):),
+     &	      FILENAME(:LEN_F)
+	ELSE
+	   WRITE(6,1045)
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	   IER = OTS$CVT_L_TI(EBULL,BULL_PARAMETER,,,)
+           WRITE(6,1046)
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):),
+     &	      FILENAME(:LEN_F)
+	END IF
+
+	GO TO 10
+
+900	WRITE(6,1000) FILENAME(:LEN_F)
+	CALL ENABLE_PRIVS		! Reset BYPASS privileges
+	RETURN
+
+1000	FORMAT(' ERROR: Error in opening file ',A,'.')
+1010	FORMAT(' ERROR: You have not read any bulletin.')
+1015	FORMAT(' ERROR: Specified message number has incorrect format:')
+1030	FORMAT(' ERROR: Following bulletin was not found: ',I)
+1040	FORMAT(' Message ',A,' written to ',A)
+1045	FORMAT(' Messages ',A,'-',$)
+1046	FORMAT('+',A,' written to ',A)
+1050	FORMAT('Subj: ',A,/)
+1060	FORMAT(/,'From: ',A,/,'Date: ',A)
+
+	END
+
+
+
+	SUBROUTINE COPY2(OUT,IN)
+
+	CALL LIB$MOVC3(8,IN,OUT)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE LOGIN
+C
+C  SUBROUTINE LOGIN
+C
+C  FUNCTION: Alerts user of new messages upon logging in.
+C
+	IMPLICIT INTEGER (A - Z)
+
+        INCLUDE 'BULLFILES.INC'
+ 
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER TODAY*24,INREAD*4
+
+	DATA CTRL_G/7/
+
+	DATA GEN_DIR1/0/	! General directory link list header
+	DATA SYS_DIR1/0/	! System directory link list header
+	DATA SYS_NUM1/0/	! System message number link list header
+	DATA SYS_BUL1/0/	! System bulletin link list header
+	DATA ALL_DIR1/0/	! Full directory link list header (for remote)
+
+	DATA PAGE/0/
+
+	DATA FIRST_WRITE/.TRUE./
+	LOGICAL FIRST_WRITE
+
+	COMMON /LOGIN_BTIM/ LOGIN_BTIM_SAVE(2)
+
+	DIMENSION NOLOGIN_BTIM(2),TODAY_BTIM(2)
+	DIMENSION NEW_BTIM(2),PASSCHANGE(2),BULLCP_BTIM(2)
+	DIMENSION LOGIN_BTIM_OLD(2),LOGIN_BTIM_NEW(2)
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	FOLDER_NAME = FOLDER
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NOLOGIN_BTIM)
+	CALL SYS_BINTIM('5-NOV-1956 11:05:56',NEW_BTIM)
+
+C
+C  Find user entry in BULLUSER.DAT to update information and
+C  to get the last date that messages were read.
+C
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_HEADER(IER)		! Get the header
+
+	IF (IER.EQ.0) THEN			! Header is present.
+	   UNLOCK 4
+	   CALL READ_USER_FILE_KEYNAME(USERNAME,IER1)
+						! Find if there is an entry
+	   IF (NEW_FLAG(1).LT.143.OR.NEW_FLAG(1).GT.143) THEN
+	      NEW_FLAG(2)=0		! If old version clear GENERIC value
+	      NEW_FLAG(1)=143		! Set new version number
+	   END IF
+	   IF (IER1.EQ.0) THEN			! There is a user entry
+	      IF (COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM).GE.0) THEN
+						! DISMAIL or SET LOGIN set
+		 IF (CLI$PRESENT('ALL')) THEN
+		    CALL COPY2(LOGIN_BTIM,TODAY_BTIM(1))
+		 ELSE
+		    RETURN			! Don't notify
+	         END IF
+	      END IF
+	      CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)
+	      CALL COPY2(LOGIN_BTIM,TODAY_BTIM)
+	      REWRITE (4) USER_ENTRY
+	      IF (SYSTEM_FLAG(1).NE.0.AND.SYSTEM_FLAG(1).NE.1) READIT = 1
+	      DO I = 1,FLONG
+		 IF (SET_FLAG(I).NE.0.OR.BRIEF_FLAG(I).NE.0.OR.
+     &		    (I.GT.1.AND.SYSTEM_FLAG(I).NE.0)) READIT = 1
+	      END DO
+	   ELSE
+	      CALL CLEANUP_LOGIN		! Good time to delete dead users
+	      CALL COPY2(READ_BTIM,NEW_BTIM)	! Make new entry
+	      DO I = 1,FLONG
+	         SET_FLAG(I) = SET_FLAG_DEF(I)
+	         BRIEF_FLAG(I) = BRIEF_FLAG_DEF(I)
+		 NOTIFY_FLAG(I) = NOTIFY_FLAG_DEF(I)
+	      END DO
+	      NEW_FLAG(1) = 143
+	      NEW_FLAG(2) = 0
+	      CALL CHECK_NEWUSER(USERNAME,DISMAIL,PASSCHANGE)
+	      IF (DISMAIL.EQ.1) THEN
+		 CALL COPY2(LOGIN_BTIM,NOLOGIN_BTIM)
+	         CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)
+	      ELSE
+	         CALL COPY2(LOGIN_BTIM_SAVE,NEW_BTIM)
+		 CALL COPY2(LOGIN_BTIM,TODAY_BTIM)
+	         DO I = 1,FLONG
+		    IF (SET_FLAG(I).NE.0) READIT = 1
+	         END DO
+		 IF (COMPARE_BTIM(PASSCHANGE,NEWEST_BTIM).LT.0) IER1 = 0
+			! Old password change indicates user is new to BULLETIN
+			! but not to system, so don't limit message viewing.
+	      END IF
+	      CALL WRITE_USER_FILE(IER)
+	      IF (IER.NE.0) THEN		! Error in writing to user file
+		 WRITE (6,1070)			! Tell user of the error
+		 CALL CLOSE_BULLUSER		! Close the user file
+		 CALL EXIT			! Go away...
+	      END IF
+	      IF (DISMAIL.EQ.1) RETURN		! Go away if DISMAIL set
+	      DIFF = -1				! Force us to look at messages
+	      CALL OPEN_BULLINF_SHARED
+	      DO I=1,FOLDER_MAX
+	         CALL COPY2(LAST_READ_BTIM(1,I),READ_BTIM)
+	      END DO
+	      WRITE (9,IOSTAT=IER) USERNAME,
+     &		((LAST_READ_BTIM(I,J),I=1,2),J=1,FOLDER_MAX)
+	      CALL CLOSE_BULLINF
+	   END IF
+	   CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_SAVE)
+	   CALL READ_USER_FILE_HEADER(IER2)	! Reset read back to header
+	END IF
+
+	IF (IER.EQ.0.AND.MINUTE_DIFF(TODAY_BTIM,BBOARD_BTIM)
+     &			.GT.BBOARD_UPDATE) THEN	! Update BBOARD mail?
+	   CALL COPY2(BBOARD_BTIM,TODAY_BTIM)
+	   REWRITE (4) USER_HEADER		! Rewrite header
+	   IF (.NOT.TEST_BULLCP()) CALL CREATE_PROCESS('BBOARD')
+	ELSE IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLUSER
+	   CALL EXIT			! If no header, no messages
+	END IF
+
+	IF (IER1.EQ.0) THEN		! Skip date comparison if new entry
+C
+C  Compare and see if messages have been added since the last time
+C  that the user has logged in or used the BULLETIN facility.
+C
+	   DIFF1 = COMPARE_BTIM(LOGIN_BTIM,READ_BTIM)
+	   IF (DIFF1.LT.0) THEN		! If read messages since last login,
+	      CALL COPY2(LOGIN_BTIM,READ_BTIM)
+		! then use read date to compare with latest bulletin date
+	   END IF			! to see if should alert user.
+
+	   IF (SYSTEM_SWITCH) THEN
+	      DIFF1 = COMPARE_BTIM(SYSTEM_LOGIN_BTIM,NEWEST_BTIM)
+	   ELSE
+	      DIFF1 = COMPARE_BTIM(LOGIN_BTIM,NEWEST_BTIM)
+	   END IF
+	END IF
+
+	CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)  ! Destroyed in UPDATE_READ
+	
+	IF (NEW_FLAG(2).NE.0.AND.NEW_FLAG(2).NE.-1) THEN
+	   CALL LIB$MOVC3(4,NEW_FLAG(2),%REF(BULL_PARAMETER))
+	   CALL SUBTIME(LOGIN_BTIM,BULL_PARAMETER(:4),IER)
+	ELSE IF (DIFF1.GT.0) THEN
+	   BULL_POINT = -1
+	   IF (READIT.EQ.1) THEN
+	      CALL UPDATE_READ(1)
+	      CALL COPY2(LOGIN_BTIM_NEW,LOGIN_BTIM)
+	      CALL READ_IN_FOLDERS
+	      CALL MODIFY_SYSTEM_LIST(1)
+	   END IF
+	   CALL CLOSE_BULLUSER
+	   RETURN
+	END IF
+
+	CALL READ_IN_FOLDERS
+	CALL MODIFY_SYSTEM_LIST(1)
+        FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//FOLDER
+
+	ENTRY LOGIN_FOLDER
+
+	IF (NEW_FLAG(2).EQ.0.OR.NEW_FLAG(2).EQ.-1.OR.FOLDER_SET) THEN
+	   CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_SAVE)
+	END IF
+
+	IF (REMOTE_SET.EQ.1) THEN	! If system remote folder, use remote
+					! info, not local login time
+	   IF (LAST_SYS_BTIM(1,FOLDER_NUMBER+1).NE.0) THEN
+	    CALL COPY2(LOGIN_BTIM,LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	    LAST_SYS_BTIM(1,FOLDER_NUMBER+1) = 0
+	    LAST_SYS_BTIM(2,FOLDER_NUMBER+1) = 0
+	   ELSE
+	    DIFF1 = COMPARE_BTIM(LOGIN_BTIM,
+     &			LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	    IF (DIFF1.LT.0) THEN
+	      CALL COPY2(LOGIN_BTIM,LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	    ELSE
+	      DIFF = MINUTE_DIFF(LOGIN_BTIM,F_NEWEST_BTIM)
+	      IF (DIFF.GE.0.AND.DIFF.LE.15) THEN  ! BULLCP updates every 15 min
+	         IER = SYS$BINTIM('0 00:15',BULLCP_BTIM)
+	         BULLCP_BTIM(1) = -BULLCP_BTIM(1) ! Convert to -delta time
+	         BULLCP_BTIM(2) = -BULLCP_BTIM(2)-1
+	         CALL LIB$SUBX(LOGIN_BTIM,BULLCP_BTIM,LOGIN_BTIM)
+	      END IF
+	    END IF
+	   END IF
+	END IF
+
+	ENTRY SHOW_SYSTEM
+
+	JUST_SYSTEM = (.NOT.LOGIN_SWITCH.AND.SYSTEM_SWITCH).OR.
+     &	        (BTEST(FOLDER_FLAG,2)
+     &		.AND..NOT.TEST_SET_FLAG(FOLDER_NUMBER)
+     &		.AND..NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER))
+
+	NGEN = 0			! Number of general messages
+	NSYS = 0			! Number of system messages
+	BULL_POINT = -1
+
+	IF (IER1.NE.0.AND.FOLDER_NUMBER.GT.0) THEN
+	   IF (LOGIN_SWITCH) THEN
+	      IF (READIT.EQ.1) THEN
+	         CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)
+	         CALL UPDATE_READ(1)
+	         CALL COPY2(LOGIN_BTIM_NEW,LOGIN_BTIM)
+	      END IF
+	      CALL CLOSE_BULLUSER
+	   END IF
+	   RETURN	! Don't overwhelm new user with lots of non-general msgs
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,2).AND.SYSTEM_SWITCH) THEN
+			! Can folder have SYSTEM messages and /SYSTEM specified?
+	   CALL COPY2(LOGIN_BTIM,SYSTEM_LOGIN_BTIM) ! Use specified login time
+						    ! for system messages.
+	END IF
+
+	IF (LOGIN_SWITCH) THEN
+	   IF (READIT.EQ.1) THEN
+	      CALL COPY2(LOGIN_BTIM_OLD,LOGIN_BTIM)
+	      CALL UPDATE_READ(1)
+	      CALL COPY2(LOGIN_BTIM_NEW,LOGIN_BTIM)
+	      CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_OLD)
+	   END IF
+	   CALL CLOSE_BULLUSER
+	END IF
+
+	IF (READIT.EQ.1.AND.FOLDER_NUMBER.GE.0.AND.REMOTE_SET.LT.3) THEN
+	   IF (LAST_SYS_BTIM(1,FOLDER_NUMBER+1).NE.0) THEN
+	      DIFF1 = COMPARE_BTIM(LOGIN_BTIM,
+     &				LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	      IF (DIFF1.LT.0) THEN
+	         CALL COPY2(LOGIN_BTIM,LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	      END IF
+	      CALL COPY2(LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &			 LOGIN_BTIM_NEW)
+	   END IF
+
+	   IF (TEST2(BRIEF_FLAG,FOLDER_NUMBER)
+     &		       .AND.TEST2(SET_FLAG,FOLDER_NUMBER)) THEN
+	      IF (.NOT.TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) GO TO 9999
+	   END IF
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED	! Get bulletin directory
+	IF (.NOT.REMOTE_SET) THEN
+	   CALL READDIR(0,IER)		! Get header info
+	ELSE
+	   NBULL = F_NBULL
+	END IF
+	   
+	CALL INIT_QUEUE(GEN_DIR1,BULLDIR_ENTRY)
+	CALL INIT_QUEUE(SYS_DIR1,BULLDIR_ENTRY)
+	CALL INIT_QUEUE(SYS_NUM1,%DESCR(ICOUNT))
+	GEN_DIR = GEN_DIR1
+	SYS_DIR = SYS_DIR1
+	SYS_NUM = SYS_NUM1
+	START = 1
+	REVERSE = 0
+	IF ((.NOT.TEST_SET_FLAG(FOLDER_NUMBER).OR.
+     &		.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER))
+     &		.AND..NOT.BTEST(FOLDER_FLAG,7)) THEN
+	   IF (REVERSE_SWITCH) REVERSE = 1
+	   IF (IER1.EQ.0) THEN
+	      CALL GET_NEWEST_MSG(LOGIN_BTIM,START)
+	      IF (START.EQ.-1) START = NBULL + 1
+	   END IF
+	END IF
+
+	IF (REMOTE_SET) THEN
+	   CALL INIT_QUEUE(ALL_DIR1,BULLDIR_ENTRY)
+	   ALL_DIR = ALL_DIR1
+	   CALL REMOTE_DIRECTORY_COMMAND(START,NBULL,
+     &					 .NOT.REVERSE,ALL_DIR,IER)
+	   IF (IER.NE.0) THEN
+	      CALL CLOSE_BULLDIR
+	      CALL DISCONNECT_REMOTE
+	      GO TO 9999
+	   END IF
+	   LAST_DIR = ALL_DIR
+	   ALL_DIR = ALL_DIR1
+	END IF
+
+	CALL GET_NODE_NUMBER(NODE_NUMBER1,NODE_AREA1)
+
+	DO ICOUNT1 = NBULL,START,-1
+	   IF (REVERSE) THEN
+	      ICOUNT = NBULL + START - ICOUNT1
+	   ELSE
+	      ICOUNT = ICOUNT1
+	   END IF
+	   IF (REMOTE_SET) THEN
+	      IF (ALL_DIR.EQ.LAST_DIR) GO TO 100
+	      CALL READ_QUEUE(%VAL(ALL_DIR),ALL_DIR,BULLDIR_ENTRY)
+	      IER = ICOUNT + 1
+	   ELSE
+	      CALL READDIR(ICOUNT,IER)
+	   END IF
+	   IF (IER1.EQ.0.AND.IER.EQ.ICOUNT+1) THEN ! Is this a totally new user?
+	      IF (.NOT.REVERSE.AND..NOT.BTEST(FOLDER_FLAG,7)) THEN 
+	         DIFF = COMPARE_BTIM(LOGIN_BTIM,MSG_BTIM) ! No, so compare date
+	         IF (DIFF.GT.0) GO TO 100
+	      END IF
+	      IGNORE = BTEST(SYSTEM,2).AND.(NODE_AREA.EQ.NODE_AREA1).AND.
+     &			(NODE_NUMBER.AND.NODE_NUMBER1)
+	      IF (.NOT.BTEST(FOLDER_FLAG,2)) SYSTEM = SYSTEM.AND.(.NOT.1)
+			! Show system msg in non-system folder as general msg
+	      IF ((USERNAME.NE.FROM.OR.SYSTEM).AND..NOT.IGNORE) THEN
+				  	! Is bulletin system or from same user?
+		 IF (SYSTEM) THEN	! Is it system bulletin? 
+		    NSYS = NSYS + 1
+		    CALL WRITE_QUEUE(%VAL(SYS_DIR),SYS_DIR,BULLDIR_ENTRY)
+		    CALL WRITE_QUEUE(%VAL(SYS_NUM),SYS_NUM,%DESCR(ICOUNT))
+	         ELSE IF (.NOT.JUST_SYSTEM) THEN
+		    IF (BTEST(FOLDER_FLAG,7)) THEN
+		       DIFF = COMPARE_BTIM
+     &			      (LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+		    ELSE IF (.NOT.SYSTEM_SWITCH) THEN
+		       DIFF = -1
+		    ELSE
+	               DIFF = COMPARE_BTIM(LOGIN_BTIM_SAVE,MSG_BTIM)
+		    END IF
+		    IF (DIFF.LT.0) THEN
+		       IF (.NOT.REVERSE.OR.BULL_POINT.EQ.-1) THEN
+		          BULL_POINT = ICOUNT - 1
+		          IF (.NOT.BTEST(FOLDER_FLAG,2).AND.
+     &			   TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &			   TEST_SET_FLAG(FOLDER_NUMBER)) GO TO 100
+		       END IF
+		       NGEN = NGEN + 1
+		       SYSTEM = ICOUNT
+		       CALL WRITE_QUEUE(%VAL(GEN_DIR),GEN_DIR,BULLDIR_ENTRY)
+		    END IF
+	         END IF
+	      END IF
+	   ELSE IF (IER.EQ.ICOUNT+1) THEN
+			! Totally new user, save only permanent system msgs
+	      IF ((SYSTEM.AND.7).EQ.3.OR.
+     &		  (SYSTEM.AND.BTEST(FOLDER_FLAG,7))) THEN
+	         NSYS = NSYS + 1
+		 CALL WRITE_QUEUE(%VAL(SYS_DIR),SYS_DIR,BULLDIR_ENTRY)
+		 CALL WRITE_QUEUE(%VAL(SYS_NUM),SYS_NUM,%DESCR(ICOUNT))
+	      ELSE IF (NGEN.EQ.0.OR.	! And save only the first non-system msg
+     &		     BTEST(FOLDER_FLAG,7)) THEN ! and SET ALWAYS folder messages
+		 SYSTEM = ICOUNT	! Save bulletin number for display
+		 IF (.NOT.REVERSE.OR.BULL_POINT.EQ.-1) THEN
+		    BULL_POINT = ICOUNT - 1
+		    IF (.NOT.BTEST(FOLDER_FLAG,2).AND.
+     &			TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &		 	TEST_SET_FLAG(FOLDER_NUMBER)) GO TO 100
+		 END IF
+		 NGEN = NGEN + 1
+		 CALL WRITE_QUEUE(%VAL(GEN_DIR),GEN_DIR,BULLDIR_ENTRY)
+	      END IF
+	   END IF
+	END DO
+100	CALL CLOSE_BULLDIR
+C
+C  Review new directory entries.  If there are system messages,
+C  copy the system bulletin into GEN_DIR file BULLSYS.SCR for outputting
+C  to the terminal.  If there are simple messages, just output the
+C  header information.
+C
+	IF (TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &			   TEST_SET_FLAG(FOLDER_NUMBER)) NGEN = 0
+
+	IF (NGEN.EQ.0.AND.NSYS.EQ.0) GO TO 9999
+
+	IF (NSYS.GT.0) THEN		! Are there any system messages?
+	   IF (FIRST_WRITE) THEN
+	      PAGE = 4		! Don't erase MAIL/PASSWORD notifies
+	      FIRST_WRITE = .FALSE.	! if this is first write to screen.
+	   END IF
+	   LENF = TRIM(FOLDER_NAME)
+	   S1 = (PAGE_WIDTH-(LENF+16))/2
+	   S2 = PAGE_WIDTH - S1 - (LENF + 16)
+	   WRITE (6,'(''+'',A,$)') CTRL_G
+	   IF (REMOTE_SET.LT.3) THEN
+	      FOLDER_NAME = FOLDER
+	   ELSE
+	      FOLDER_NAME = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	   END IF
+	   WRITE (6,1026) FOLDER_NAME(:LENF)		! Yep...
+	   PAGE = PAGE + 1
+	   CTRL_G = 0		! Don't ring bell for non-system bulls
+	   CALL OPEN_BULLFIL_SHARED
+	   CALL INIT_QUEUE(SYS_BUL1,INPUT)
+	   SYS_BUL = SYS_BUL1
+	   SYS_DIR = SYS_DIR1
+	   SYS_NUM = SYS_NUM1
+	   NSYS_LINE = 0
+	   DO J=1,NSYS
+	      CALL READ_QUEUE(%VAL(SYS_DIR),SYS_DIR,BULLDIR_ENTRY)
+	      IF (REMOTE_SET) THEN
+	         CALL READ_QUEUE(%VAL(SYS_NUM),SYS_NUM,%DESCR(ICOUNT))
+	         WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 5,ICOUNT
+	         IF (IER.GT.0) THEN
+	            CALL DISCONNECT_REMOTE
+	         ELSE
+	            CALL GET_REMOTE_MESSAGE(IER)
+	         END IF
+		 IF (IER.GT.0) THEN
+		    CALL CLOSE_BULLFIL
+		    GO TO 9999
+		 END IF
+	      END IF
+ 	      INPUT = ' '
+	      CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+	      NSYS_LINE = NSYS_LINE + 1
+	      ILEN = LINE_LENGTH + 1
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      DO WHILE (ILEN.GT.0)	! Copy bulletin to SYS_BUL link list
+		 CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+		 NSYS_LINE = NSYS_LINE + 1
+		 CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END DO
+	      IF (ILEN.LT.0) THEN
+		 CALL CLOSE_BULLFIL
+		 GO TO 9999
+	      END IF
+	      IF (J.LT.NSYS.AND.SEPARATE.NE.' ') THEN
+ 	         INPUT = ' '
+	         CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+		 DO I=1,PAGE_WIDTH
+		    INPUT(I:I) = SEPARATE
+		 END DO
+		 CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+	         NSYS_LINE = NSYS_LINE + 2
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLFIL
+	   SYS_BUL = SYS_BUL1
+	   ILEN = 0
+	   I = 1
+	   WIDTH = PAGE_WIDTH
+	   LEFT = .FALSE.
+	   DO WHILE (I.LE.NSYS_LINE.OR.ILEN.GT.0)  ! Write out system messages
+	      IF (ILEN.EQ.0) THEN
+	         CALL READ_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+		 ILEN = TRIM(INPUT)
+		 I = I + 1
+	      END IF
+	      IF (SYS_BUL.NE.0) THEN
+		 IF (PAGE.EQ.PAGE_LENGTH-2.AND.PAGING) THEN
+							! If at end of screen
+		    WRITE(6,1080)	! Ask for input to proceed to next page
+		    CALL GET_INPUT_NOECHO_PROMPT(INREAD(:1),
+     &			'HIT any key for next page....')
+	            WRITE (6,'(1X)')
+	            CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+		    PAGE = 1
+	            INREAD = '+'
+		 ELSE IF (WIDTH.EQ.PAGE_WIDTH.OR.LEFT) THEN 
+		    PAGE = PAGE + 1
+	            INREAD = ' '
+		 END IF
+		 IF (LEFT) THEN
+ 		    WRITE(6,1050) INREAD(:1)//INPUT(:ILEN)
+		    LEFT = .FALSE.
+	            ILEN = 0
+	            INREAD = '+'
+		 ELSE IF (ILEN.LE.WIDTH) THEN
+ 		    WRITE(6,1060) INREAD(:1)//INPUT(:ILEN)
+		    WIDTH = PAGE_WIDTH
+		    ILEN = 0
+		 ELSE
+		    DO WHILE (WIDTH.GT.0.AND.INPUT(WIDTH:WIDTH).NE.' ')
+	               WIDTH = WIDTH - 1
+		    END DO
+		    WRITE(6,1060) INREAD(:1)//INPUT(:WIDTH)
+	            INPUT = INPUT(WIDTH+1:)
+		    ILEN = ILEN - WIDTH
+		    DO WHILE (INPUT(:1).EQ.' '.AND.ILEN.GT.0)
+		       ILEN = ILEN - 1
+		       INPUT = INPUT(2:)
+	            END DO
+                    IF (INPUT(ILEN:ILEN).EQ.' ') THEN
+	               CONTINUE
+		    ELSE IF (ALPHA(INPUT(ILEN:ILEN))) THEN
+		       INPUT = INPUT(:ILEN)//' '
+		       ILEN = ILEN + 1
+		    ELSE
+		       INPUT = INPUT(:ILEN)//'  '
+		       ILEN = ILEN + 2
+		    END IF
+		    WIDTH = PAGE_WIDTH - ILEN
+		    IF (WIDTH.GT.0) THEN
+		       IF (ILEN.GT.0) LEFT = .TRUE.
+		    ELSE
+	               WIDTH = PAGE_WIDTH
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (NGEN.EQ.0) THEN
+	      WRITE (6,'(A)')		! Write delimiting blank line
+	   END IF
+	   PAGE = PAGE + 1
+	END IF
+
+	ENTRY REDISPLAY_DIRECTORY
+
+	GEN_DIR = GEN_DIR1
+	IF (NGEN.GT.0) THEN		! Are there new non-system messages?
+	   LENF = TRIM(FOLDER_NAME)
+	   S1 = (PAGE_WIDTH-13-LENF)/2
+	   S2 = PAGE_WIDTH-S1-13-LENF
+	   IF (PAGE+7+NGEN.GT.PAGE_LENGTH.AND.PAGE.GT.0) THEN
+	      WRITE(6,1080)		! Ask for input to proceed to next page
+	      CALL GET_INPUT_NOECHO_PROMPT(INREAD(:1),	! Get terminal input
+     &			'HIT any key for next page....')
+	      WRITE (6,'(1X)')
+	      CALL LIB$ERASE_PAGE(1,1)	! Clear the screen
+	      WRITE (6,'(''+'',A,$)') CTRL_G
+	      WRITE(6,1028) 'New '//FOLDER_NAME(:LENF)//' messages'
+	      PAGE = 1
+	   ELSE
+	      IF (FIRST_WRITE) THEN
+		 PAGE = 4		  ! Don't erase MAIL/PASSWORD notifies
+	         FIRST_WRITE = .FALSE. ! if this is first write to screen.
+	      END IF
+	      WRITE (6,'(''+'',A,$)') CTRL_G
+	      WRITE(6,1027) 'New '//FOLDER_NAME(:LENF)//' messages'
+	      PAGE = PAGE + 1
+	   END IF
+	   WRITE(6,1020)
+	   WRITE(6,1025)
+	   PAGE = PAGE + 2
+	   I = 0
+	   DO WHILE (I.LT.NGEN)
+	      I = I + 1
+	      CALL READ_QUEUE(%VAL(GEN_DIR),GEN_DIR,BULLDIR_ENTRY)
+	      CALL CONVERT_ENTRY_FROMBIN_FOLDER
+	      N = MAX(INT(LOG10(REAL(SYSTEM)))+1,3)
+	      N1 = MAX(1,6-N)
+	      IF (PAGE.EQ.PAGE_LENGTH-2.AND.PAGING) THEN ! If at end of screen
+		 WRITE(6,1080)	! Ask for input to proceed to next page
+		 CALL GET_INPUT_NOECHO_PROMPT(INREAD(:1),
+     &		'HIT Q(Quit listing) or any other key for next page....')
+	         CALL STR$UPCASE(INREAD(:1),INREAD(:1))
+	         WRITE (6,'(1X)')
+	         CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+		 PAGE = 1
+		 IF (INREAD(:1).EQ.'Q') THEN
+		    I = NGEN		! Quit directory listing
+		    WRITE(6,'(''+Quitting directory listing.'')')
+		 ELSE
+		    WRITE(6,1040) '+'//DESCRIP(:53),FROM,DATE(:6),SYSTEM
+		 END IF
+					! Bulletin number is stored in SYSTEM
+	      ELSE
+		 PAGE = PAGE + 1
+		 WRITE(6,1040) ' '//DESCRIP(:53),FROM,DATE(:6),SYSTEM
+	      END IF
+	   END DO
+	   IF ((.NOT.FOLDER_SET.AND.BTEST(SET_FLAG(1),0).AND.DIFF1.LE.0)
+     &		.OR.(FOLDER_SET.AND.TEST_SET_FLAG(FOLDER_NUMBER))) THEN
+	      PAGE = 0	! Don't reset page counter if READNEW not set,
+	   END IF	! as no prompt to read is generated.
+	END IF
+C
+C  Instruct users how to read displayed messages if READNEW not selected.
+C
+	IF (.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &		TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE(6,1030)
+	ELSE IF (NGEN.EQ.0) THEN
+	   ILEN = 57 + INDEX(COMMAND_PROMPT,'>') - 1
+	   S1 = (PAGE_WIDTH-ILEN)/2
+	   S2 = PAGE_WIDTH - S1 - ILEN
+	   WRITE(6,1035) 'The '//COMMAND_PROMPT(:ILEN-57)//
+     &		'/SYSTEM command can be used to reread these messages.'
+	   PAGE = PAGE + 1
+	ELSE
+	   FLEN = TRIM(FOLDER_NAME)
+	   IF (FOLDER_NUMBER.EQ.0) FLEN = -1
+	   ILEN = 30 + INDEX(COMMAND_PROMPT,'>') - 1 + FLEN
+	   S1 = (PAGE_WIDTH-ILEN)/2
+	   S2 = PAGE_WIDTH - S1 - ILEN
+	   IF (FOLDER_NUMBER.EQ.0) THEN
+	      WRITE(6,1035) 'Type ' //COMMAND_PROMPT(:ILEN-29)//
+     &		' to read these messages.'
+	   ELSE
+	      WRITE(6,1035) 'Type '//COMMAND_PROMPT(:ILEN-30-FLEN)
+     &		//' '//FOLDER_NAME(:FLEN)//
+     &		' to read these messages.'
+	   END IF
+	   PAGE = PAGE + 1
+	END IF
+
+9999	IF (LOGIN_SWITCH) THEN
+	   CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_NEW)
+	   CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM_OLD)
+	END IF
+	RETURN
+
+1020	FORMAT(' Description',43X,'From',9X,'Date',3X,'Number')
+1025	FORMAT(' -----------',43X,'----',9X,'----',3X,'------')
+1026	FORMAT(' ',<S1>('*'),A,' System Messages',<S2>('*'))
+1027	FORMAT(/,' ',<S1>('*'),A,<S2>('*'))
+1028	FORMAT('+',<S1>('*'),A,<S2>('*'))
+1030	FORMAT(' ',<PAGE_WIDTH>('*'))
+1035	FORMAT(' ',<S1>('*'),A,<S2>('*'))
+1040	FORMAT(A<53>,2X,A12,1X,A6,<N1>X,I<N>)
+1050	FORMAT(A,$)
+1060	FORMAT(A)
+1070	FORMAT(' ERROR: Cannot add new entry to user file.')
+1080	FORMAT(' ',/)
+
+	END
+
+
+	
+
+	SUBROUTINE GET_NODE_NUMBER_OTHER(NODE_NUMBER,NODE_AREA,NODE_NAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	CHARACTER*(*) NODE_NAME
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,SYI$_NODE_AREA,%LOC(NODE_AREA))
+	CALL ADD_2_ITMLST(4,SYI$_NODE_NUMBER,%LOC(NODE_NUMBER))
+	CALL END_ITMLST(GETSYI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETSYIW(,,NODE_NAME(:TRIM(NODE_NAME)),
+     &			%VAL(GETSYI_ITMLST),,,)	! Get Info command.
+
+	IF (.NOT.IER) THEN
+	   WRITE (6,'('' ERROR: Specified node name not found.'')')
+	   NODE_AREA = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DIRECTORY_HEADER(OUTLINE,PRINTING,EXTRACTING,EXPIRATION,
+     &		OUT,DELETING,UNDELETING)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	CHARACTER*(*) OUTLINE
+
+	IF (REMOTE_SET.GE.3) THEN
+	   WRITE (OUTLINE,'('' ['',I,''-'',I,'']'')')
+     &						F_START,F_NBULL
+	ELSE
+	   WRITE (OUTLINE,'('' [1-'',I,'']'')') NBULL
+	END IF
+	DO WHILE (INDEX(OUTLINE,'- ').GT.0)
+	   I = INDEX(OUTLINE,'- ')
+	   OUTLINE(I+1:) = OUTLINE(I+2:)
+	END DO
+	DO WHILE (INDEX(OUTLINE,'[ ').GT.0)
+	   I = INDEX(OUTLINE,'[ ')
+	   OUTLINE(I+1:) = OUTLINE(I+2:)
+	END DO
+	DO WHILE (INDEX(OUTLINE,'  ').LT.TRIM(OUTLINE))
+	   I = INDEX(OUTLINE,'  ')
+	   OUTLINE(I:) = OUTLINE(I+1:)
+	END DO
+	OUTLINE = FOLDER_NAME(:TRIM(FOLDER_NAME))//OUTLINE
+	BULL_PARAMETER = ' '
+	IF (READ_TAG) THEN
+	   IF (BTEST(READ_TAG,1)) THEN
+	      BULL_PARAMETER = 'MARKED'
+	   ELSE
+	      BULL_PARAMETER = 'SEEN'
+	   END IF
+	   IF (BTEST(READ_TAG,3)) THEN
+	      BULL_PARAMETER = 'UN'//BULL_PARAMETER
+	   END IF
+	END IF
+	IF (PRINTING) THEN
+	   BULL_PARAMETER = 'PRINTING '//BULL_PARAMETER
+	ELSE IF (EXTRACTING) THEN
+	   BULL_PARAMETER = 'EXTRACTING '//BULL_PARAMETER
+	ELSE IF (DELETING) THEN
+	   BULL_PARAMETER = 'DELETING '//BULL_PARAMETER
+	ELSE IF (UNDELETING) THEN
+	   BULL_PARAMETER = 'UNDELETING '//BULL_PARAMETER
+	END IF
+
+	IF (OUT.EQ.6) THEN 
+           WRITE (OUT,'(''+'',A,<PAGE_WIDTH-TRIM(BULL_PARAMETER)-
+     &		TRIM(OUTLINE)>X,A)')
+     &		BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &		OUTLINE(:TRIM(OUTLINE))
+           IF (EXPIRATION) THEN
+	      WRITE(OUT,1005) '    #'
+	   ELSE
+	      WRITE(OUT,1000) '    #'
+	   END IF
+	ELSE
+           WRITE (OUT,'(A,<PAGE_WIDTH-TRIM(BULL_PARAMETER)-
+     &		TRIM(OUTLINE)>X,A)')
+     &		BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &		OUTLINE(:TRIM(OUTLINE))
+           IF (EXPIRATION) THEN
+	      WRITE(OUT,1005) '   #'
+	   ELSE
+	      WRITE(OUT,1000) '   #'
+	   END IF
+	END IF
+
+1000	FORMAT(A,1X,'Description',43X,'From',9X,'Date',/)
+1005	FORMAT(A,1X,'Description',43X,'From',8X,'Expires',/)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_NEW_OR_SINCE(NEW,SINCE,IER,DATETIME)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	INTEGER TODAY(2)
+
+	CHARACTER DATETIME*24
+
+	IF (SINCE) THEN	 		! Was /SINCE specified?
+   	   IF (DATETIME.EQ.'TODAY') THEN	! TODAY is the default.
+	      	     IER = SYS$BINTIM('-- 00:00:00.00',TODAY)
+	      CALL GET_MSGKEY(TODAY,MSG_KEY)
+	   ELSE
+	      CALL SYS_BINTIM(DATETIME,MSG_BTIM)
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   END IF
+	   CALL READDIR_KEYGE(IER)
+	ELSE IF (NEW) THEN	! was /NEW specified?
+	   IF (REMOTE_SET.LT.3) THEN
+	      DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &		       F_NEWEST_BTIM)
+	      IF (DIFF.GE.0) THEN
+		 IER = 0
+	         RETURN
+	      ELSE
+	         CALL GET_MSGKEY(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				MSG_KEY)
+	      END IF
+	      CALL READDIR_KEYGE(IER)
+	   ELSE
+	      CALL NEWS_GET_NEWEST_MESSAGE(IER)
+	   END IF
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin1.for b/decus/vmslt00a/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..66b637b8c6e76aeade07bf5097268378a91b17bb
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin1.for
@@ -0,0 +1,2500 @@
+C
+C  BULLETIN1.FOR, Version 4/8/98
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE MAIL
+C
+C  SUBROUTINE MAIL
+C
+C  FUNCTION: Sends message which you have read to user via DEC mail.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /SENDTO/ SENDTO
+	CHARACTER*256 SENDTO
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	INCLUDE 'BULLDIR.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	IF (BTEST(CAPTIVE(-1),1)) THEN
+	   WRITE (6,'('' ERROR: MAIL invalid from DISMAIL account.'')')
+	   RETURN
+	END IF
+
+	IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	   WRITE(6,'('' ERROR: You have not read any message.'')')
+	   RETURN			! And return
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+
+	IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	   WRITE(6,'('' ERROR: Specified message was not found.'')')
+	   CALL CLOSE_BULLDIR		! If not, then error out
+	   RETURN
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	IF (CLI$PRESENT('EDIT')) THEN
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	END IF
+
+	OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &	   RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Error in opening scratch file.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('HEADER')) THEN		! Printout header?
+	   IF (EXDATE(8:11).LT.'1995') THEN
+	      IF (REMOTE_SET.NE.3) THEN
+		 INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   (DELETED)'
+	      ELSE
+		 INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+	      END IF
+	   ELSE IF ((SYSTEM.AND.4).EQ.4) THEN	! Is entry shutdown bulletin?
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Expires on shutdown'
+	   ELSE IF ((SYSTEM.AND.2).EQ.2) THEN	! Is entry permanent bulletin?
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Permanent'
+	   ELSE
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)//
+     &				'   Expires:   '//EXDATE//' '//EXTIME(:5)
+	   END IF
+	   IF ((SYSTEM.AND.1).EQ.1) THEN		! System bulletin?
+	      INPUT = INPUT(:TRIM(INPUT))//' / System'
+	   END IF
+	   WRITE (3,'(A)') INPUT(:TRIM(INPUT))
+	END IF
+
+	HEAD = CLI$PRESENT('HEADER')
+
+	CALL OPEN_BULLFIL_SHARED	! Open BULLETIN file
+
+	ILEN = LINE_LENGTH + 1
+
+	CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	   IF (HEAD) WRITE(3,1060) INPUT(7:ILEN)
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	ELSE IF (HEAD) THEN
+	   WRITE(3,1060) FROM
+	END IF
+
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	   IF (HEAD) WRITE(3,1050) INPUT(7:ILEN)
+	   SUBJECT_LINE = INPUT(7:ILEN)
+	ELSE
+	   IF (HEAD) WRITE(3,1050) DESCRIP
+	   IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   SUBJECT_LINE = DESCRIP
+	END IF
+
+	IF (CLI$PRESENT('SUBJECT')) THEN
+	   IER = CLI$GET_VALUE('SUBJECT',SUBJECT_LINE,LEN_D)
+	END IF
+
+	DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	END DO
+
+	CLOSE (UNIT=3)			! Message copy completed
+
+	CALL CLOSE_BULLFIL
+
+	LEN_D = TRIM(SUBJECT_LINE)
+	IF (LEN_D.EQ.0) THEN
+	   SUBJECT_LINE = 'BULLETIN message.'
+	   LEN_D = TRIM(SUBJECT_LINE)
+	END IF
+
+	I = 1
+	DO WHILE (I.LE.LEN_D)
+	   IF (SUBJECT_LINE(I:I).EQ.'"') THEN
+	      IF (LEN_D.EQ.64) THEN
+		 SUBJECT_LINE(I:I) = '`'
+	      ELSE
+		 SUBJECT_LINE = SUBJECT_LINE(:I)//'"'//SUBJECT_LINE(I+1:)
+		 I = I + 1
+		 LEN_D = LEN_D + 1
+	      END IF
+	   END IF
+	   I = I + 1
+	END DO
+
+	LEN_S = 0
+	DO WHILE (CLI$GET_VALUE('RECIPIENTS',SENDTO(LEN_S+1:),I)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get all the usernames
+	   LEN_S = LEN_S + I + 1
+	   SENDTO(LEN_S:LEN_S) = ','
+	END DO
+	LEN_S = LEN_S - 1
+
+	I = 1		! Must change all " to """ in MAIL recipients
+	DO WHILE (I.LE.LEN_S)
+	   IF (SENDTO(I:I).EQ.'"') THEN
+	      SENDTO = SENDTO(:I)//'""'//SENDTO(I+1:)
+	      I = I + 2
+	      LEN_S = LEN_S + 2
+	   END IF
+	   I = I + 1
+	END DO
+
+	IF (CLI$PRESENT('EDIT')) THEN
+	   CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	   CONTEXT = 0
+	   IER =  LIB$FIND_FILE('SYS$LOGIN:BULL.SCR',INPUT,CONTEXT)
+	   VERSION = INDEX(INPUT,';') + 1
+	   IF (INPUT(VERSION:VERSION).EQ.'1') THEN
+	      CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	      WRITE (6,'('' ERROR: No message mailed.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	CALL DISABLE_PRIVS
+	CALL SENDMAIL('SYS$LOGIN:BULL.SCR',SENDTO(:LEN_S)
+     &			,SUBJECT_LINE,STATUS)
+C       CALL LIB$SPAWN('$MAIL SYS$LOGIN:BULL.SCR '//SENDTO(:LEN_S)
+C     &    //'/SUBJECT="'//SUBJECT_LINE(:LEN_D)//'"',,,,,,STATUS)
+C	IF (.NOT.STATUS) CALL SYS_GETMSG(STATUS)
+
+	CALL ENABLE_PRIVS
+	CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+
+	RETURN
+
+1050	FORMAT('Description: ',A,/)
+1060	FORMAT('From: ',A)
+
+	END
+
+
+
+	SUBROUTINE MODIFY_FOLDER
+C
+C  SUBROUTINE MODIFY_FOLDER
+C
+C  FUNCTION: Modifies a folder's information.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER RESPONSE*32
+
+	IF (.NOT.FOLDER_ACCESS
+     &		 (USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   WRITE (6,'('' ERROR: No privileges to modify folder.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('NAME')) THEN
+	   IF (REMOTE_SET) THEN
+	      WRITE (6,'('' ERROR: Cannot change name of'',
+     &				'' remote folder.'')')
+	      RETURN
+	   ELSE
+	      CALL CLI$GET_VALUE('NAME',FOLDER1,LEN_P)
+	      IF (LEN_P.GT.44) THEN
+		 WRITE (6,'('' ERROR: Folder name cannot be larger
+     &				than 44 characters.'')')
+		 RETURN
+	      END IF
+	   END IF
+	ELSE
+	   FOLDER1 = FOLDER
+	END IF
+
+	INIT_NEWSFEED = .FALSE.
+
+	NEWSGROUP = .FALSE.
+	MAILTO = 0
+
+	IF (CLI$PRESENT('DESCRIPTION')) THEN
+	   WRITE (6,'('' Enter one line description of folder.'')')
+	   LENF = 81
+	   DO WHILE (LENF.GT.80)
+	      CALL GET_LINE(FOLDER1_DESCRIP,LENF)	! Get input line
+	      IF (LENF.LE.0) THEN
+		 WRITE (6,'('' ERROR: Folder modification aborted.'')')
+		 RETURN
+	      ELSE IF (LENF.GT.80) THEN			! If too many characters
+		 WRITE (6,'('' ERROR: Description must be < 80 characters.'')')
+	         RETURN
+	      ELSE
+		 FOLDER1_DESCRIP = FOLDER1_DESCRIP(:LENF) ! End fill with spaces
+	      END IF
+	   END DO
+	   I = INDEX(FOLDER1_DESCRIP,'<')
+	   J = INDEX(FOLDER1_DESCRIP,'>')
+	   IF (I.GT.0.AND.J.GT.I.AND.(INDEX(FOLDER1_DESCRIP(I:),'@').LT.1
+     &	       .OR.INDEX(FOLDER1_DESCRIP(I:),'@').GT.J-I+1).AND.
+     &	       (INDEX(FOLDER1_DESCRIP(I:),'.')
+     &	       .LE.J-I+1.AND.INDEX(FOLDER1_DESCRIP(I:),'.').GT.0)) THEN
+	      NEWSGROUP = .TRUE.
+	      WRITE (6,'('' Init news feed counter to feed '',
+     &			 ''all messages in news group (Y),'')')
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &		 'or set to feed only new messages (N,default) ? ')
+	      INIT_NEWSFEED = RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y'
+	      I = INDEX(FOLDER1_DESCRIP,'[')
+	      J = INDEX(FOLDER1_DESCRIP,']')
+	   END IF
+	   IF (I.GT.0.AND.J.GT.I.AND.
+     &	       (INDEX(FOLDER1_DESCRIP(I:),'@').GT.1.AND.
+     &	       INDEX(FOLDER1_DESCRIP(I:),'@').LT.J-I+1)) THEN
+	      MAILTO = 1
+	   END IF
+	   IF (I.GT.0.AND.J.GT.I.AND.(INDEX(FOLDER1_DESCRIP(I:),'.')
+     &	       .GT.J-I+1.OR.INDEX(FOLDER1_DESCRIP(I:),'.').EQ.0)
+     &	       .AND.MAILTO.EQ.0.AND..NOT.BTEST(FOLDER_FLAG,11)
+     &	       .AND..NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Have you specified '//
+     &		   'an email address in the description? (default=N) ')
+	      IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') MAILTO = 1
+	   END IF
+	   IF (MAILTO.EQ.1.AND..NOT.BTEST(FOLDER_FLAG,11).AND.
+     &	       .NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	      WRITE (6,'('' A mailing address has been specified.'')')
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Will messages be '//
+     &		'sent to and received from this address? (default=N) ')
+	      IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') THEN
+	         MAILTO = 2
+		 WRITE (6,'('' SET POST_ONLY will be issued.'')')
+	      ELSE
+		 MAILTO = 3
+		 WRITE (6,'('' SET ADD_ONLY will be issued.'')')
+	      END IF
+	   END IF
+	ELSE
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP
+	END IF
+
+	IF (CLI$PRESENT('OWNER')) THEN
+	   CALL CLI$GET_VALUE('OWNER',FOLDER1_OWNER,LEN_P)
+	   IF (LEN_P.GT.12) THEN
+	      WRITE (6,'('' ERROR: Owner name must be < 13 characters.'')')
+	      RETURN
+	   ELSE IF (CLI$PRESENT('ID')) THEN
+	      IER = CHKPRO(FOLDER1_OWNER)
+	   ELSE
+	      CALL GET_UAF
+     &		   (FOLDER1_OWNER,USERB1,GROUPB1,ACCOUNTB1,FLAGS,IER)
+	   END IF
+	   IF (.NOT.IER) THEN
+	      WRITE (6,'('' ERROR: Owner name is not valid username.'')')
+	      RETURN
+	   ELSE IF (LEN_P.GT.LEN(FOLDER1_OWNER)) THEN
+	      WRITE (6,'('' ERROR: Folder owner name too long.'')')
+	      RETURN
+	   ELSE IF (.NOT.SETPRV_PRIV()) THEN
+	      WRITE(6,'('' Enter password of new owner: '',A)') CHAR(10)
+	      CALL GET_INPUT_NOECHO(RESPONSE)
+	      IF (TRIM(RESPONSE).EQ.0) THEN
+		 WRITE (6,'('' ERROR: No password entered.'')')
+		 RETURN
+	      END IF
+	      WRITE (6,'('' Attempting to verify password name...'')')
+	      OPEN (UNIT=10,NAME='SYS$NODE"'//
+     &		   FOLDER1_OWNER(:TRIM(FOLDER1_OWNER))
+     &		   //' '//RESPONSE(:TRIM(RESPONSE))//'"::',
+     &		   TYPE='SCRATCH',IOSTAT=IER)
+	      CLOSE (UNIT=10)
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' ERROR: Password is invalid.'')')
+		 RETURN
+	      ELSE
+		 WRITE (6,'('' Password was verified.'')')
+	      END IF
+	   ELSE
+	      FOLDER1_OWNER = FOLDER1_OWNER(:LEN_P)
+	   END IF
+	ELSE
+	   FOLDER1_OWNER = FOLDER_OWNER
+	END IF
+
+	CALL OPEN_BULLFOLDER		! Open folder file
+
+	IF (CLI$PRESENT('NAME')) THEN
+	   READ (7,IOSTAT=IER,KEY=FOLDER1,KEYID=0)
+	   				! See if folder exists
+	   IF (IER.EQ.0) THEN
+	      WRITE (6,'('' ERROR: Folder name already exists.'')')
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   END IF
+	END IF
+
+	CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	IF (IER.EQ.0.AND.CLI$PRESENT('NAME')) THEN
+	   LEN_F = TRIM(FOLDER_DIRECTORY)
+	   IER = LIB$RENAME_FILE(FOLDER_DIRECTORY(:LEN_F)//
+     &		FOLDER(:TRIM(FOLDER))//'.*',FOLDER_DIRECTORY(:LEN_F)//
+     &		FOLDER1(:TRIM(FOLDER1))//'.*')
+	   IF (.NOT.IER) THEN
+	      I = 0
+	      IER1 = LIB$FIND_FILE(FOLDER_DIRECTORY(:LEN_F)//
+     &		FOLDER(:TRIM(FOLDER))//'.*',INPUT,I)
+	   END IF
+	   IF (IER.OR..NOT.IER1) THEN
+	      FOLDER_FILE = FOLDER_DIRECTORY(:LEN_F)//FOLDER1
+	      FOLDER_NAME = FOLDER1
+	      IER = 0
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   IF (CLI$PRESENT('OWNER')) THEN
+	      CALL CHKACL
+     &		(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',IER)
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+		 CALL ADD_ACL(FOLDER1_OWNER,'R+W+C',IER)
+		 CALL DEL_ACL(FOLDER_OWNER,'R+W+C',IER)
+	      END IF
+	   END IF
+	   FOLDER = FOLDER1
+	   FOLDER_OWNER = FOLDER1_OWNER
+	   FOLDER_DESCRIP = FOLDER1_DESCRIP
+	   DELETE (7)
+	   IF (CLI$PRESENT('ID')) THEN
+	      FOLDER_FLAG = IBSET(FOLDER_FLAG,6)
+	   ELSE
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,6)
+	   END IF
+	   IF (NEWSGROUP) FOLDER_FLAG = IBSET(FOLDER_FLAG,4)
+	   IF (MAILTO.EQ.2) FOLDER_FLAG = IBSET(FOLDER_FLAG,10)
+	   IF (MAILTO.EQ.3) FOLDER_FLAG = IBSET(FOLDER_FLAG,11)
+	   IF (INIT_NEWSFEED) THEN
+	      F_LAST = 0
+	   ELSE IF (NEWSGROUP) THEN
+	      CALL CLOSE_BULLFOLDER
+	      CALL OPEN_BULLNEWS_SHARED
+	      I = INDEX(FOLDER_DESCRIP,'<') + 1
+	      J = INDEX(FOLDER_DESCRIP,'>') - 1
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER_DESCRIP(I:J),IER)
+	      CALL CLOSE_BULLNEWS
+	      CALL OPEN_BULLFOLDER
+	      F_LAST = F1_NBULL
+	   END IF
+	   CALL WRITE_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) WRITE (6,'('' Folder successfully modified.'')')
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Folder modification aborted.'')')
+	END IF
+
+	CALL CLOSE_BULLFOLDER
+
+	RETURN
+	END
+
+
+
+	FUNCTION FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) USERNAME,FOLDER_OWNER
+
+	IF (SETPRV_PRIV()) THEN
+	   FOLDER_ACCESS = .TRUE.
+	ELSE IF (BTEST(FOLDER_FLAG,6)) THEN	! If folder owner is ID
+	   FOLDER_ACCESS = CHKPRO(FOLDER_OWNER)
+	ELSE
+	   FOLDER_ACCESS = USERNAME.EQ.FOLDER_OWNER
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE MOVE(DELETE_ORIGINAL)
+C
+C  SUBROUTINE MOVE
+C
+C  FUNCTION: Moves message from one folder to another.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REMOTE_READ_MESSAGE/ SCRATCH_R1
+	DATA SCRATCH_R1 /0/
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /HEADER/ HEADER
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	COMMON /NEWS2BULL/ NEWS2BULL
+
+	COMMON /FEED/ FEED
+
+        COMMON /MAIL_INFO/ USE_INFROM
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /BULLCP_NEWS/ BULLCP_NEWS
+
+	EXTERNAL CLI$_ABSENT,BULLETIN_SUBCOMMANDS
+
+	LOGICAL DELETE_ORIGINAL
+
+	CHARACTER SAVE_FOLDER*44,POST_SUBJECT*256,TODAY*24
+	CHARACTER SCRFILE*18
+
+	DATA TEMP_FILE/.FALSE./
+
+	DIMENSION BTIM(2)
+
+	ORIGINAL = CLI$PRESENT('ORIGINAL')
+
+	IF (ORIGINAL.AND..NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: You have no privileges to keep''
+     &			,'' original owner.'')')
+	   RETURN
+	END IF
+
+	ALL = CLI$PRESENT('ALL')
+
+	MERGE = CLI$PRESENT('MERGE')
+
+	SAVE_BULL_POINT = BULL_POINT
+
+	FROM_REMOTE = REMOTE_SET
+	CALL CLI$GET_VALUE('FOLDER',FOLDER1)
+	IF (INDEX(FOLDER1,'.').GT.0) CALL LOWERCASE(FOLDER1)
+	TO_NEWS = TEST_NEWS(FOLDER1)
+	IF (.NOT.BULLCP_NEWS.AND.FOLDER.EQ.FOLDER1) THEN
+	   WRITE (6,'('' ERROR: Destination cannot be same as'',
+     &		      '' current location.'')')
+	   RETURN
+	END IF
+
+	IER1 = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER1.EQ.%LOC(CLI$_ABSENT).AND..NOT.ALL) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no message has been read
+	      WRITE(6,'('' ERROR: You are not reading any message.'')')
+	      RETURN			! and return
+	   END IF
+
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(BULL_POINT,IER)		! Get message directory entry
+	   IF (IER.NE.BULL_POINT+1.OR.BULL_POINT.NE.SAVE_BULL_POINT) THEN
+	      WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      CALL CLOSE_BULLDIR
+	      BULL_POINT = SAVE_BULL_POINT
+	      RETURN
+	   END IF
+
+	   NUM_COPY = 1
+	ELSE
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(0,IER)		! Get message directory entry
+	   IF (NBULL.EQ.0) THEN		! Were messages found?
+	      WRITE(6,'('' ERROR: No messages were found.'')')
+	      CALL CLOSE_BULLDIR
+	      RETURN
+	   END IF
+
+	   IF (IER1.NE.%LOC(CLI$_ABSENT)) THEN
+	      CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER1)
+	      IF (EBULL.GT.F_NBULL) EBULL = F_NBULL
+	      IF (SBULL.LE.0.OR.IER1.NE.0) THEN
+		 WRITE (6,'(A)')
+     &		  ' ERROR: Specified message number has incorrect format.'
+		 CALL CLOSE_BULLDIR
+		 RETURN
+	      ELSE
+		 NUM_COPY = EBULL - SBULL + 1
+		 BULL_POINT = SBULL
+	      END IF
+	      IF (NUM_COPY.GT.1) ALL = .TRUE.
+	      IF (INDEX(BULL_PARAMETER,'LAST').GT.0.AND.ORIGINAL) THEN
+	         NEWGROUP = .TRUE.	! Kludgey way of detecting new2bull
+	         NEXT = .TRUE.		! If SBULL does not exist, will find
+              ELSE			! next message after SBULL
+	         SBULL1 = SBULL
+	   	 CALL READDIR(SBULL,IER)
+	   	 IF (IER.NE.SBULL+1.OR.SBULL.NE.SBULL1) THEN
+		    WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      	    CALL CLOSE_BULLDIR
+	      	    RETURN
+	         END IF
+	      END IF
+	   ELSE IF (ALL) THEN
+	      NUM_COPY = NBULL
+	      BULL_POINT = 1
+	      NEWGROUP = .TRUE.
+	      NEXT = .TRUE.
+	   END IF
+	END IF
+
+	IF (REMOTE_SET.OR.REMOTE_SET.EQ.4) THEN
+	   IF (.NOT.TEMP_FILE) THEN
+	      OPEN (UNIT=12,FILE='REMOTE.BULLDIR',
+     &		 STATUS='SCRATCH',FORM='UNFORMATTED',IOSTAT=IER)
+	      IF (IER.EQ.0) THEN
+		 OPEN (UNIT=11,FILE='REMOTE.BULLFIL',
+     &		    STATUS='SCRATCH',IOSTAT=IER,
+     &		    ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &		    FORM='UNFORMATTED')
+	      END IF
+	   ELSE
+	      REWIND (12,IOSTAT=IER)
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      TEMP_FILE = .TRUE.
+	      CALL OPEN_BULLFIL
+	      CALL READDIR(0,IER)
+	      I = BULL_POINT - 1
+	      IER = I + 1
+	      NBLOCK = 1
+	      LAST = BULL_POINT+NUM_COPY-1
+	      NUM_COPY = 0
+	      DO WHILE (I.LT.LAST.AND.IER.EQ.I+1)
+		 I = I + 1
+		 CALL READDIR(I,IER)
+		 IF (IER.EQ.I+1.AND.I.LE.LAST) THEN
+		    CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+		    IF (REMOTE_SET) THEN
+		       CALL REMOTE_READ_MESSAGE(I,IER1)
+		       IF (IER1.GT.0) THEN
+			  CALL DISCONNECT_REMOTE
+		       ELSE
+			  CALL GET_REMOTE_MESSAGE(IER1)
+		       END IF
+		    ELSE
+		       IER1 = 0
+		    END IF
+		    IF (LENGTH.EQ.0) IER1 = 1	! Don't allow empty messages
+		    IF (IER1.EQ.0) THEN
+		       SCRATCH_R = SCRATCH_R1
+		       DO J=1,LENGTH
+			  IF (REMOTE_SET) THEN
+			     CALL READ_QUEUE(%VAL(SCRATCH_R),
+     &					SCRATCH_R,INPUT(:128))
+			  ELSE
+			     READ (1'BLOCK+J-1,IOSTAT=IER1) INPUT(:128)
+			  END IF
+			  WRITE (11'NBLOCK+J-1,IOSTAT=IER1) INPUT(:128)
+		       END DO
+		    END IF
+		    NEWS2BULL = NEWS2BULL.AND..NOT.TO_NEWS.AND.ORIGINAL
+		    IF (IER1.EQ.0.AND..NOT.NEWS2BULL) THEN
+		       BLOCK = NBLOCK
+		       NBLOCK = NBLOCK + LENGTH
+		       WRITE (12,IOSTAT=IER1) BULLDIR_ENTRY
+		    END IF
+		    IF (TO_NEWS.AND.ORIGINAL) THEN
+		       WRITE (12,IOSTAT=IER1) NEWS_MSGID
+		    END IF
+		    IF (IER1.NE.0) THEN
+		       I = IER
+		    ELSE IF (.NOT.NEWS2BULL) THEN
+		       NUM_COPY = NUM_COPY + 1
+		    END IF
+		    NEWS2BULL = .FALSE.
+		 END IF
+	      END DO
+	      CALL CLOSE_BULLFIL
+	   END IF
+	   IF (IER1.NE.0.OR..NOT.TEMP_FILE.OR.NUM_COPY.EQ.0) THEN
+	      WRITE(6,'('' ERROR: Copy aborted. Remote folder problem.'')')
+	      CLOSE (UNIT=12)
+	      CLOSE (UNIT=11)
+	      TEMP_FILE = .FALSE.
+	      CALL CLOSE_BULLDIR
+	      RETURN
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	SAVE_FOLDER = FOLDER
+	SAVE_FOLDER_NUMBER = FOLDER_NUMBER
+
+	FOLDER_NUMBER = -1	! Use FOLDER as key rather than FOLDER_NUMBER
+	FROM_BULL_POINT = BULL_POINT
+	CALL SELECT_FOLDER(.FALSE.,IER)
+
+	IER1 = .TRUE.
+
+	POST_NEWS = (REMOTE_SET.EQ.4.AND..NOT.BULLCP_NEWS).OR.REMOTE_SET.EQ.3
+
+	POST_FEED = .FALSE.
+	SLIST = 0
+	IF (.NOT.IER) THEN
+	   WRITE (6,'('' ERROR: Cannot access specified folder.'')')
+	ELSE IF (READ_ONLY.OR.(MERGE.AND.REMOTE_SET.GT.0)) THEN
+	   IF (READ_ONLY) THEN
+	      WRITE (6,'('' ERROR: No access to write into folder.'')')
+	   ELSE
+	      WRITE (6,'('' ERROR: /MERGE invalid into remote folder.'')')
+	   END IF
+	   IER1 = .FALSE.
+	ELSE IF (REMOTE_SET.EQ.0) THEN
+	   IF (.NOT.CLI$PRESENT('LOCAL').AND.NEWS_FEED()) THEN
+	      SLIST = INDEX(FOLDER_DESCRIP,'<') + 1
+	      FOLDER1_DESCRIP =
+     &		FOLDER_DESCRIP(SLIST:INDEX(FOLDER_DESCRIP,'>')-1)
+	      POST_FEED = .TRUE.
+	   END IF
+	   IF (NEWS_FEED()) THEN
+	      SLIST = INDEX(FOLDER_DESCRIP,'[') + 1
+	   ELSE
+	      SLIST = INDEX(FOLDER_DESCRIP,'<') + 1
+	   END IF
+	   IF (SLIST.GT.1) THEN
+	      IF (NEWS_FEED()) THEN
+	         ELIST = INDEX(FOLDER_DESCRIP,']') - 1
+	      ELSE
+	         ELIST = INDEX(FOLDER_DESCRIP,'>') - 1
+	      END IF
+	   END IF
+	   IF (CLI$PRESENT('LOCAL').AND..NOT.BULLCP_NEWS) SLIST = 0
+	END IF
+
+	IF (.NOT.IER.OR..NOT.IER1) THEN
+	   FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	   IF (.NOT.IER) THEN
+	      FOLDER = SAVE_FOLDER
+	      BULL_POINT = SAVE_BULL_POINT
+	   ELSE
+	      FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	      FOLDER1 = SAVE_FOLDER
+	      CALL SELECT_FOLDER(.FALSE.,IER1)
+	   END IF
+	   BULL_POINT = SAVE_BULL_POINT
+	   CLOSE (UNIT=12)
+	   CLOSE (UNIT=11)
+	   TEMP_FILE = .FALSE.
+	   RETURN
+	END IF
+C
+C  Add bulletin to bulletin file and directory entry for to directory file.
+C
+	IF (POST_NEWS.OR.(POST_FEED.AND.SLIST.LE.1)) THEN
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='SCRATCH',CARRIAGECONTROL='LIST')
+	   SCRFILE = 'SYS$LOGIN:BULL.SCR'
+	END IF
+	IF (.NOT.POST_NEWS) THEN
+	   CALL OPEN_BULLDIR			! Prepare to add dir entry
+	   IF (REMOTE_SET.EQ.4) THEN            ! In case exdate has bad date
+	      IF (FOLDER_BBEXPIRE.GT.0) THEN
+		 EX = FOLDER_BBEXPIRE
+	      ELSE
+		 EX = NEWS_EXPIRE_DEFAULT
+	      END IF
+	      CALL GET_EXDATE(EXDATE,EX)
+	      CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	      EXTIME = TODAY(13:)
+	   END IF
+	   CALL OPEN_BULLFIL			! Prepare to add bulletin
+
+	   CALL READDIR(0,IER)			! Get NBLOCK
+	   IF (IER.EQ.0.AND.REMOTE_SET.LT.3) NBLOCK = 0
+	END IF
+
+	FOLDER1_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//SAVE_FOLDER
+
+	IF (.NOT.FROM_REMOTE.AND.FROM_REMOTE.NE.4) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	      OPEN (UNIT=12,FILE=FOLDER1_FILE(:TRIM(FOLDER1_FILE))
+     &		//'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &		RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &		ORGANIZATION='INDEXED',IOSTAT=IER,
+     &		KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	   END DO
+
+	   IF (IER.EQ.0) THEN
+	      DO WHILE (FILE_LOCK(IER,IER1))
+		 OPEN (UNIT=11,FILE=FOLDER1_FILE(:TRIM(FOLDER1_FILE))
+     &		   //'.BULLFIL',STATUS='UNKNOWN',IOSTAT=IER,
+     &		   ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &		   FORM='UNFORMATTED')
+	      END DO
+	   END IF
+	ELSE
+	   IER= 0
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+	   SAVE_HEADER = HEADER
+	   IF (CLI$PRESENT('HEADER')) THEN
+	      HEADER = .TRUE.
+	   ELSE
+	      HEADER = .FALSE.
+	   END IF
+	END IF
+
+	IF (MERGE) CALL INITIALIZE_MERGE(IER)
+
+	START_BULL_POINT = BULL_POINT
+
+	IF (IER.EQ.0) THEN
+	   IF (FROM_REMOTE.OR.FROM_REMOTE.EQ.4) THEN
+	      REWIND (12)
+	   ELSE
+	      READ (12,KEYID=0,KEY=FROM_BULL_POINT-1,IOSTAT=IER)
+	   END IF
+	END IF
+
+	DO WHILE (NUM_COPY.GT.0.AND.IER.EQ.0)
+	   READ (12,IOSTAT=IER) BULLDIR_ENTRY
+	   IF ((FROM_REMOTE.OR.FROM_REMOTE.EQ.4).AND.
+     &	       (TO_NEWS.AND.ORIGINAL)) THEN
+	      READ (12,IOSTAT=IER) NEWS_MSGID
+	   END IF
+	   NUM_COPY = NUM_COPY - 1
+
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   CALL CONVERT_ENTRY_FROMBIN_FOLDER
+
+	   IF (REMOTE_SET.GE.3) SYSTEM = 0
+
+	   IF (FROM_REMOTE.GE.3.AND.REMOTE_SET.LE.3) THEN
+	      SYSTEM = 0
+	      IF (FOLDER_BBEXPIRE.GT.0) THEN
+		 CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      ELSE IF (FOLDER_BBEXPIRE.EQ.-1) THEN   ! Permanent message
+		 EXDATE = '5-NOV-2100'
+		 SYSTEM = 2
+	      ELSE IF (EX_BTIM(1).EQ.0.AND.EX_BTIM(2).EQ.0) THEN
+		 CALL GET_EXDATE(EXDATE,14)
+	      END IF
+	   ELSE IF (REMOTE_SET.EQ.4.AND.ORIGINAL) THEN
+	      IF (EX_BTIM(1).NE.0.OR.EX_BTIM(2).NE.0) THEN
+		 LIMIT = NEWS_F_EXPIRE_LIMIT
+		 IF (LIMIT.EQ.0) LIMIT = NEWS_EXPIRE_LIMIT_DEFAULT
+		 IF (LIMIT.GT.0) THEN
+		    CALL GET_EXDATE(EXDATE,LIMIT)
+		    CALL SYS_BINTIM(EXDATE,BTIM)
+		    IF (COMPARE_BTIM(BTIM,EX_BTIM).LT.0) THEN
+		       CALL COPY2(EX_BTIM,BTIM)
+		    END IF
+		 END IF
+		 CALL SYS$ASCTIM(,EXDATE,EX_BTIM,)
+		 IF (COMPARE_DATE(EXDATE,' ').LE.0) THEN
+		    IER = 0
+		    GO TO 100
+		 END IF
+	      ELSE
+		 IF (FOLDER_BBEXPIRE.GT.0) THEN
+		    EX = FOLDER_BBEXPIRE
+		 ELSE
+		    EX = NEWS_EXPIRE_DEFAULT
+		 END IF
+		 IF (F_LAST.EQ.0) THEN
+		    EX = EX + COMPARE_DATE(DATE,' ')
+		    IF (EX.LE.0) THEN
+		       IER = 0
+		       GO TO 100
+		    END IF
+		 END IF
+		 CALL GET_EXDATE(EXDATE,EX)
+	      END IF
+	      CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	      EXTIME = TODAY(13:)
+	   END IF
+
+	   IF (.NOT.BTEST(FOLDER_FLAG,2).OR.	! Not system folder?
+     &		 .NOT.SETPRV_PRIV()) THEN	! Or no privileges?
+	      SYSTEM = IBCLR(SYSTEM,0)		! Remove system bit
+	   END IF
+
+	   IF (BTEST(SYSTEM,2).AND.		! Shutdown message?
+     &	    (.NOT.BTEST(FOLDER_FLAG,2).OR.	! Not system folder?
+     &		 .NOT.SETPRV_PRIV())) THEN	! Or no privileges?
+	      SYSTEM = IBCLR(SYSTEM,2)		! Remove shutdown bit
+	      WRITE (6,'('' ERROR: No privileges to add'',
+     &				'' shutdown message.'')')
+	      IF (FOLDER_BBEXPIRE.GT.0) THEN
+		 CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+		 WRITE (6,'('' Expiration will be '',I,'' days.'')')
+     &				FOLDER_BBEXPIRE
+	      ELSE
+		 CALL GET_EXDATE(EXDATE,14)
+		 WRITE (6,'('' Expiration will be '',I,'' days.'')') 14
+	      END IF
+	      EXTIME = '00:00:00.00'
+	   ELSE IF (BTEST(SYSTEM,1).AND.	! Permanent?
+     &		F_EXPIRE_LIMIT.GT.0.AND..NOT.   ! Expiration limit present?
+     &		FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	      WRITE (6,'('' ERROR: No privileges to add'',
+     &				'' permanent message.'')')
+	      WRITE (6,'('' Expiration will be '',I,'' days.'')')
+     &				F_EXPIRE_LIMIT
+	      SYSTEM = IBCLR(SYSTEM,1)
+	      CALL GET_EXDATE(EXDATE,F_EXPIRE_LIMIT)
+	      EXTIME = '00:00:00.00'
+	   END IF
+
+	   IF (.NOT.ORIGINAL) THEN	! If not /ORIGINAL
+	      FROM = USERNAME		! Specify owner
+	   END IF
+
+	   IF (REMOTE_SET.EQ.1) THEN
+	      WRITE (REMOTE_UNIT,'(A)',IOSTAT=IER) 2
+	      IF (IER.NE.0) CALL ERROR_AND_EXIT
+	   END IF
+
+	   IF (SLIST.GT.1.OR.POST_NEWS.OR.POST_FEED) THEN
+	      BLOCK_SAVE = BLOCK
+	      LENGTH_SAVE = LENGTH
+	      IF (SLIST.GT.1) THEN
+		 OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		   RECL=LINE_LENGTH,CARRIAGECONTROL='LIST')
+	         SCRFILE = 'SYS$LOGIN:BULL.SCR'
+		 IF (IER.NE.0) THEN
+	      	    OPEN(UNIT=3,FILE='BULL.SCR',IOSTAT=IER,
+     &		       RECL=LINE_LENGTH,CARRIAGECONTROL='LIST')
+	      	    SCRFILE = 'BULL.SCR'
+		 END IF
+	      ENDIF
+	      ILEN = LINE_LENGTH + 1
+
+	      INFROM = FROM
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	         INFROM = INPUT(7:)
+		 CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+		 POST_SUBJECT = INPUT(7:ILEN)
+	      ELSE
+		 POST_SUBJECT = DESCRIP
+		 IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	      END IF
+
+	      DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+		 CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		 IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(1:ILEN)
+	      END DO
+
+	      REWIND (UNIT=3)
+
+	      IF (POST_NEWS.OR.POST_FEED) THEN
+	         USE_INFROM = ORIGINAL
+	         IF (CLI$PRESENT('LOCAL')) NEWS2BULL = .TRUE.
+	         CALL NEWS_POST
+     &		    (SCRFILE(:TRIM(SCRFILE)),.TRUE.,IER,POST_SUBJECT)
+		 NEWS2BULL = .FALSE.
+	      END IF
+	      IF (SLIST.GT.1) THEN
+		 CLOSE (UNIT=3)
+		 USE_INFROM = ORIGINAL
+		 IF (BTEST(FOLDER_FLAG,10).OR.BTEST(FOLDER_FLAG,15)) THEN
+	            CALL RESPOND_MAIL(SCRFILE(:TRIM(SCRFILE)),
+     &		       FOLDER_DESCRIP(SLIST:ELIST),
+     &		       POST_SUBJECT(:TRIM(POST_SUBJECT)),STATUS)
+		 ELSE
+	            CALL RESPOND_MAIL(SCRFILE(:TRIM(SCRFILE)),
+     &		       FOLDER_DESCRIP(SLIST:ELIST),
+     &	   	       FOLDER(:TRIM(FOLDER))//' folder message: '//
+     &		       POST_SUBJECT(:TRIM(POST_SUBJECT)),STATUS)
+		 END IF
+		 CALL LIB$DELETE_FILE(SCRFILE(:TRIM(SCRFILE))//';')
+	      ELSE IF (POST_FEED.OR.POST_NEWS) THEN
+		 REWIND (UNIT=3)
+	      END IF
+	      BLOCK = BLOCK_SAVE
+	      LENGTH = LENGTH_SAVE
+	   END IF
+	   IF (.NOT.POST_NEWS) THEN
+	      IF (MERGE) CALL ADD_MERGE_TO(IER)
+
+	      IF (REMOTE_SET.EQ.4) CALL SET_BULLFIL_UPDATE
+
+	      IF (IER.EQ.0) THEN
+		 NBLOCK = NBLOCK + 1
+
+		 DO I=BLOCK,BLOCK+LENGTH-1
+		    READ (11'I,IOSTAT=IER) INPUT(:128)
+		    IF (IER.EQ.0) THEN
+		       CALL WRITE_BULL_FILE(NBLOCK,INPUT(:128))
+		    END IF
+		    NBLOCK = NBLOCK + 1
+		 END DO
+	      END IF
+
+	      IF (IER.EQ.0) THEN
+		 IF (MERGE) THEN
+		    CALL ADD_MERGE_FROM(IER)
+		 ELSE
+		    IF (.NOT.ORIGINAL) SYSTEM = IBSET(SYSTEM,4)
+		    CALL ADD_ENTRY	! Add the new directory entry
+		 END IF
+		 BULL_POINT = BULL_POINT + 1
+	      END IF
+	   END IF
+100	   CONTINUE
+	END DO
+
+	IF (SLIST.LT.1.AND.POST_NEWS.OR.POST_FEED) CLOSE (UNIT=3)
+
+	IF (MERGE) CALL ADD_MERGE_REST(IER)
+
+	IF (.NOT.POST_NEWS) CALL CLOSE_BULLFIL
+
+	IF (.NOT.(TO_NEWS.AND.ORIGINAL.AND.TEMP_FILE)) THEN
+	   CLOSE (UNIT=11)
+	   CLOSE (UNIT=12)
+	   TEMP_FILE = .FALSE.
+	END IF
+
+	IF (FOLDER_NUMBER.GE.0.AND.IER.EQ.0.AND..NOT.POST_NEWS
+     &		.AND.FOLDER_NUMBER.LT.FOLDER_MAX) THEN
+	   DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &			       F_NEWEST_BTIM)
+	   CALL UPDATE_FOLDER			! Update folder info
+C
+C  If user is adding message, an no new messages, update last read time for
+C  folder, so user is not alerted of new message which is owned by user.
+C
+	   IF (DIFF.GE.0) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),F_NEWEST_BTIM)
+	   END IF
+	END IF
+
+	IF (.NOT.POST_NEWS) CALL CLOSE_BULLDIR	! Totally finished with add
+
+	IF (IER.EQ.0) THEN
+	   IF (TEST_BULLCP().NE.2)
+     &	      WRITE (6,'('' Successful copy to folder '',A)')
+     &		FOLDER(:TRIM(FOLDER))//'.'
+	   IF (MERGE) THEN
+	      CALL LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &		  '.BULLDIR;-1')
+	   END IF
+	ELSE IF (MERGE) THEN
+	   WRITE (6,'('' ERROR: Copy aborted. No files copied.'')')
+	ELSE
+	   WRITE (6,'('' ERROR: Copy aborted. '',I,'' files copied.'')')
+     &			BULL_POINT - START_BULL_POINT
+	END IF
+
+	IF (.NOT.POST_NEWS) HEADER = SAVE_HEADER
+	IF (BULLCP_NEWS) RETURN
+
+	IF (INDEX(INCMD,' ').EQ.TRIM(INCMD)+1)
+     &	   INCMD = INCMD(:TRIM(INCMD))//' '//FOLDER1
+
+	FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	FOLDER1 = SAVE_FOLDER
+	CALL SELECT_FOLDER(.FALSE.,IER1)
+
+	BULL_POINT = SAVE_BULL_POINT
+
+	IF (DELETE_ORIGINAL.AND.IER.EQ.0) THEN
+	   IF (FROM_REMOTE.AND.ALL) THEN
+	      WRITE (6,'('' WARNING: Original messages not deleted.'')')
+	      WRITE (6,'('' Multiple deletions not possible for '',
+     &			''remote folders.'')')
+	   ELSE
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL DELETE_MSG
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE PRINT(PRINT_NUM,OPEN_IT)
+C
+C  SUBROUTINE PRINT
+C
+C  FUNCTION:  Print header to queue.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SJCDEF)'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER*32 QUEUE,TEST
+
+	INTEGER*2 IOSB(4)
+	EQUIVALENCE (IOSB(1),JBC_ERROR)
+
+	CHARACTER*32 FORM
+
+	PARAMETER FF = CHAR(12)
+
+	DATA FIRST /.TRUE./, CHANGED /.FALSE./
+
+	OPENED = .FALSE.
+
+	IF (CLI$PRESENT('NOW').AND..NOT.FIRST.AND.
+     &	    INCMD(:4).EQ.'PRIN') THEN
+	   WRITE (6,'('' Printing all previously queued messages.'')')
+	   GO TO 200
+	ELSE IF (.NOT.FIRST) THEN
+	   IER = CLI$GET_VALUE('QUEUE',TEST,TLEN)
+	   CHANGED = TEST(:TLEN).NE.QUEUE(:QLEN).AND.TLEN.GT.0
+	   CHANGED = CHANGED.OR.CLI$PRESENT('NOTIFY').NE.NOTIFY
+	   IER = CLI$GET_VALUE('FORM',TEST,FLEN)
+	   CHANGED = CHANGED.OR.(TEST(:TLEN).NE.FORM(:FLEN).AND.TLEN.GT.0)
+	   IF (CHANGED) THEN
+	      WRITE (6,'('' Printing all previously queued messages.'')')
+	      GO TO 200
+	   END IF
+	END IF
+
+        IF (INCMD(:4).EQ.'PRIN') THEN
+	   IF (CLI$PRESENT('CANCEL')) THEN 
+	      WRITE (6,'('' Cancelling all previously queued messages.'')')
+	      CLOSE (UNIT=24,DISPOSE='DELETE')
+	      FIRST = .TRUE.
+	      RETURN
+	   END IF
+	END IF
+
+50	IF (PRINT_NUM.EQ.0) THEN
+	   IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	      CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+	      IF (EBULL.GT.F_NBULL) EBULL = F_NBULL
+	   ELSE IF (OPENED) THEN
+	      CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	      GO TO 150
+	   ELSE IF (CLI$PRESENT('ALL')) THEN
+	      SBULL = 1
+	      EBULL = F_NBULL
+	      IER = 0
+	   ELSE IF (BULL_POINT.EQ.0) THEN  ! No.  Have we just read a bulletin?
+	      WRITE(6,1010)		  ! No, then error.
+	      RETURN
+	   ELSE
+	      SBULL = BULL_POINT
+	      EBULL = SBULL
+	      IER = 0
+	   END IF
+	   IF (SBULL.LE.0.OR.IER.NE.0.OR.EBULL.LT.SBULL) THEN
+	      WRITE (6,1015)
+	      IF (OPENED) THEN
+		 CALL CLOSE_BULLFIL
+		 CALL CLOSE_BULLDIR
+	      END IF
+	      WRITE (6,'(1X,A)') BULL_PARAMETER(:LEN_P)
+	      RETURN
+	   END IF
+	ELSE
+	   SBULL = PRINT_NUM
+	   EBULL = SBULL
+	END IF
+
+	IF (FIRST) THEN
+	   QLEN = 0
+	   IER = CLI$GET_VALUE('QUEUE',QUEUE,QLEN) 	! Get queue name
+	   IF (QLEN.EQ.0) THEN
+	      QUEUE = 'SYS$PRINT'
+	      QLEN = TRIM(QUEUE)
+	   END IF
+
+	   NOTIFY = CLI$PRESENT('NOTIFY')
+
+	   FLEN = 0
+	   IER = CLI$GET_VALUE('FORM',FORM,FLEN)	 ! Get form name
+
+	   CALL DISABLE_PRIVS
+
+	   OPEN(UNIT=24,FILE='SYS$LOGIN:BULL.LIS',ERR=900,IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+
+	   CALL ENABLE_PRIVS
+	END IF
+
+	IF (OPEN_IT) THEN
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL OPEN_BULLFIL_SHARED
+	   OPENED = .TRUE.
+	END IF
+
+	HEAD = CLI$PRESENT('HEADER')
+
+	DO I=SBULL,EBULL
+	   I1 = I
+	   CALL READDIR(I,IER)		! Get info for specified message
+	   IF (IER.NE.I+1.OR.I.GT.EBULL.OR.(.NOT.CLI$PRESENT
+     &		('ALL').AND.I1.EQ.SBULL.AND.I.NE.SBULL)) THEN
+	      IF (REMOTE_SET.NE.3.OR.I1.EQ.SBULL) WRITE(6,1030) I1
+	      IF (I1.GT.SBULL) GO TO 100
+	      CLOSE (UNIT=24,DISPOSE='DELETE')
+	      IF (OPEN_IT) THEN
+		 CALL CLOSE_BULLFIL
+		 CALL CLOSE_BULLDIR
+	      END IF
+	      RETURN
+	   ELSE IF (REMOTE_SET) THEN
+	      CALL REMOTE_READ_MESSAGE(I,IER1)
+	      IF (IER1.GT.0) THEN
+		 CALL DISCONNECT_REMOTE
+	      ELSE
+		 CALL GET_REMOTE_MESSAGE(IER1)
+	      END IF
+	      IF (IER1.NE.0) GO TO 100
+	   END IF
+
+	   IF (.NOT.FIRST) THEN
+	      WRITE (24,'(A)') FF
+	   ELSE
+	      FIRST = .FALSE.
+	   END IF
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (HEAD) THEN
+		 WRITE(24,1060) INPUT(7:ILEN),DATE//' '//TIME(:8)
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE IF (HEAD) THEN
+	      WRITE(24,1060) FROM,DATE//' '//TIME(:8)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      IF (HEAD) WRITE(24,1050) INPUT(7:ILEN)
+	   ELSE
+	      IF (HEAD) WRITE(24,1050) DESCRIP
+	      IF (ILEN.GT.0) WRITE (24,'(A)') INPUT(:ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0) WRITE (24,'(A)') INPUT(1:ILEN)
+	   END DO
+	END DO
+
+100	IF (PRINT_NUM.EQ.0) THEN
+	   IER = OTS$CVT_L_TI(SBULL,BULL_PARAMETER,,,)
+	   IF (SBULL.EQ.EBULL) THEN
+	      WRITE(6,1040)
+     &		 BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	   ELSE
+	      WRITE(6,1045)
+     &		 BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	      IER = OTS$CVT_L_TI(EBULL,BULL_PARAMETER,,,)
+	      WRITE(6,1046)
+     &		 BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	   END IF
+
+1040	   FORMAT(' Message ',A,' sent to printer.')
+1045	   FORMAT(' Messages ',A,$)
+1046	   FORMAT('+-',A,' sent to printer.')
+	   GO TO 50
+	ELSE IF (OPEN_IT) THEN
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	END IF
+
+150	IF (.NOT.CLI$PRESENT('NOW').OR.INCMD(:4).NE.'PRIN') RETURN
+
+	ENTRY PRINT_NOW
+
+200	IF (FIRST) RETURN
+
+	FIRST = .TRUE.
+
+	CLOSE (UNIT=24)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(18,SJC$_FILE_SPECIFICATION,
+     &		%LOC('SYS$LOGIN:BULL.LIS'))
+
+	CALL ADD_2_ITMLST(QLEN,SJC$_QUEUE,%LOC(QUEUE))
+	CALL ADD_2_ITMLST(0,SJC$_DELETE_FILE,0)
+
+	IF (NOTIFY) CALL ADD_2_ITMLST(0,SJC$_NOTIFY,0)
+
+	IF (FLEN.GT.0) THEN
+	   CALL ADD_2_ITMLST(FLEN,SJC$_FORM_NAME,%LOC(FORM))
+	END IF
+
+	CALL DISABLE_PRIVS
+
+	CALL ADD_2_ITMLST(4,SJC$_ENTRY_NUMBER_OUTPUT,%LOC(JOBNUM))
+
+	CALL END_ITMLST(SJC_ITMLST)
+
+	IER=SYS$SNDJBCW(,%VAL(SJC$_ENTER_FILE),,%VAL(SJC_ITMLST),IOSB,,)
+	IF (IER.AND.(.NOT.JBC_ERROR)) THEN
+	   CALL SYS_GETMSG(JBC_ERROR)
+	   IER = LIB$DELETE_FILE('SYS$LOGIN:BULL.LIS;')
+	ELSE IF (.NOT.IER) THEN
+	   CALL SYS_GETMSG(IER)
+	   IER = LIB$DELETE_FILE('SYS$LOGIN:BULL.LIS;')
+	ELSE
+	   IER = OTS$CVT_L_TI(JOBNUM,BULL_PARAMETER,,,)
+	   IF (IER) WRITE (6,'('' Job BULL (queue '',A,'', entry '',A,
+     &	      '') started on '',A)') QUEUE(:QLEN),
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):),QUEUE(:QLEN)
+	END IF
+
+	CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+
+	IF (CHANGED) THEN
+	   CHANGED = .FALSE.
+	   GO TO 50
+	END IF
+
+	RETURN
+
+900	CALL ERRSNS(IDUMMY,IER)
+	CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+	WRITE(6,1000)
+	CALL SYS_GETMSG(IER)
+	RETURN
+
+1000	FORMAT(' ERROR: Unable to open temporary file
+     &	 SYS$LOGIN:BULL.LIS for printing.')
+1010	FORMAT(' ERROR: You have not read any message.')
+1015	FORMAT(' ERROR: Specified message number has incorrect format:')
+1030	FORMAT(' ERROR: Following bulletin was not found: ',I)
+1050	FORMAT('Description: ',A,/)
+1060	FORMAT('From: ',A,/,'Date: ',A)
+
+	END
+
+
+
+
+	SUBROUTINE READ_MSG(READ_COUNT,BULL_READ)
+C
+C  SUBROUTINE READ_MSG
+C
+C  FUNCTION: Reads a specified bulletin.
+C
+C  PARAMETER:
+C	READ_COUNT - Variable to store the record in the message file
+C		that READ will read from.  Must be set to 0 to indicate
+C		that it is the first read of the message.  If -1,
+C		READ will search for the last message in the message file
+C		and read that one.  If -2, just display header information.
+C	BULL_READ - Message number to be read.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /PAGE/ PAGE_LENGTH,REAL_PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /READ_DISPLAY/ LINE_OFFSET
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /HEADER/ HEADER
+
+	COMMON /NEXT/ NEXT
+	LOGICAL NEXT /.FALSE./
+
+	COMMON /POST/ POSTTIME
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /THREAD/ THREAD
+	DATA THREAD /.FALSE./
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	DATA SCRATCH_B1/0/,LAST_THREAD/.FALSE./
+
+	CHARACTER TODAY*12,DATETIME*24,BUFFER*(INPUT_LENGTH)
+	CHARACTER HEADLINE*132
+
+	LOGICAL SINCE,PAGE
+
+	EXTERNAL CLI$_NEGATED
+
+	FIRST = BULL_READ.LT.F_START
+	KILL = BTEST(BULL_USER_CUSTOM,3)
+	BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,3)
+
+	POSTTIME = .TRUE.
+
+	CALL LIB$ERASE_PAGE(1,1)		! Clear screen
+	END = 0					! Nothing outputted on screen
+
+	IF (READ_COUNT.GT.0) GO TO 100		! Skip init steps if this is
+						! not first page of bulletin
+
+	IF (INCMD(:4).EQ.'READ'.OR.INCMD(:4).EQ.'LAST'.OR.
+     &	    INCMD(:4).EQ.'BACK'.OR.INCMD(:3).EQ.'CUR'.OR.
+     &	    INCMD(:4).EQ.'FIRS'.OR.INCMD(:1).EQ.'N') THEN
+	   IF (CLI$PRESENT('HEADER')) THEN
+	      HEADER = .TRUE.
+	   ELSE IF (CLI$PRESENT('HEADER').EQ.%LOC(CLI$_NEGATED)) THEN
+	      HEADER = .FALSE.
+	   END IF
+	   ROTC = CLI$PRESENT('ROTATE')
+	END IF
+
+	SINCE = .FALSE.
+	NEW = .FALSE.
+	PAGE = .TRUE.
+	THREAD = .FALSE.
+
+	IER = 0
+
+	IF (.NOT.PAGING) PAGE = .FALSE.
+	IF (INCMD(:4).EQ.'READ') THEN		! If READ command...
+	   POSTTIME = CLI$PRESENT('POST')
+	   THREAD = CLI$PRESENT('THREADS')
+	   IF (CLI$PRESENT('MARKED')) THEN
+	      READ_TAG = 1 + IBSET(0,1)
+	   ELSE IF (CLI$PRESENT('SEEN')) THEN
+	      READ_TAG = 1 + IBSET(0,2)
+	   ELSE IF (CLI$PRESENT('UNMARKED').OR.
+     &		   CLI$PRESENT('MARKED').EQ.%LOC(CLI$_NEGATED)) THEN
+	      READ_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+	   ELSE IF (CLI$PRESENT('UNSEEN').OR.
+     &		    CLI$PRESENT('SEEN').EQ.%LOC(CLI$_NEGATED)) THEN
+	      READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+	   ELSE IF (CLI$PRESENT('ALL')) THEN
+	      READ_TAG = IBSET(0,1) + IBSET(0,2)
+	      IF (REMOTE_SET.GE.3) THEN
+		 BULL_READ = F_START
+	      ELSE
+		 BULL_READ = 1
+	      END IF
+	   END IF
+	   IF (READ_TAG) THEN
+	      IF (.NOT.(FOLDER_NUMBER.GE.0.OR.REMOTE_SET.EQ.3)) THEN
+		 WRITE (6,'('' ERROR: Invalid qualifier'',
+     &			    '' with remote folder.'')')
+		 READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+		 GO TO 9999
+	      END IF
+	      CALL GET_FIRST_TAG(FOLDER_NUMBER,IER1,BULL_POINT)
+	   END IF
+
+	   IF (.NOT.CLI$PRESENT('PAGE')) PAGE = .FALSE.
+	   IF (CLI$PRESENT('SINCE').AND.
+     &	       .NOT.THREAD) THEN		! was /SINCE specified?
+	      IER = CLI$GET_VALUE('SINCE',DATETIME)
+	      IF (DATETIME.EQ.'TODAY') THEN	! TODAY is the default.
+		 IER = SYS$BINTIM('-- 00:00:00.00',TODAY)
+		 CALL GET_MSGKEY(TODAY,MSG_KEY)
+	      ELSE
+		 CALL SYS_BINTIM(DATETIME,MSG_BTIM)
+		 CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      END IF
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL READDIR_KEYGE(IER)
+	      CALL CLOSE_BULLDIR
+	   ELSE IF (CLI$PRESENT('NEW').OR.(THREAD.AND..NOT.
+     &		CLI$PRESENT('SINCE').AND..NOT.CLI$PRESENT('BULLETIN_NUMBER')
+     &		.AND.(.NOT.LAST_THREAD
+     &	        .OR.LAST_THREAD_NUMBER.NE.FOLDER_NUMBER)
+     &		.AND.CLI$PRESENT('NEW').NE.%LOC(CLI$_NEGATED))) THEN
+	      NEW = .TRUE.
+	      IF (REMOTE_SET.LT.3) THEN
+		 DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				 F_NEWEST_BTIM)
+		 IF (DIFF.GE.0) THEN
+		    WRITE (6,'('' No new messages are present.'')')
+		    GO TO 9999
+		 ELSE
+		    CALL GET_MSGKEY(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &							  MSG_KEY)
+		 END IF
+		 CALL OPEN_BULLDIR_SHARED
+                 IER = 0
+		 DO WHILE (IER.EQ.0)
+		    CALL READDIR_KEYGE(IER)
+	   	    IF (IER.NE.0.AND.BULL_TAG.AND.BTEST(BULL_TAG,1)) THEN
+		       CALL GET_THIS_TAG(FOLDER_NUMBER,IER1,IER,DUMMY)
+		       IF (IER1.EQ.0) THEN
+	                  CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					MSG_BTIM)
+		          CALL GET_MSGKEY(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					MSG_KEY)
+			  IER = 0
+	               END IF
+		    ELSE IF (IER.EQ.0) THEN
+		       CALL CLOSE_BULLDIR
+		       WRITE (6,'('' No more messages are present.'')')
+		       GO TO 9999
+	            END IF
+		    IF (IER.NE.0.AND.THREAD.AND..NOT.BTEST(SYSTEM,8)) THEN
+		       IER = 0
+		    END IF
+	         END DO
+		 CALL CLOSE_BULLDIR
+	      ELSE
+                 IER = 0
+		 SKIPPED_THREAD = .FALSE.
+		 IF (THREAD) CALL OPEN_BULLDIR_SHARED
+		 DO WHILE (IER.EQ.0)
+		    IF (.NOT.SKIPPED_THREAD) THEN
+		       CALL NEWS_GET_NEWEST_MESSAGE(IER)
+		       BULL_READ = IER
+		    END IF
+		    IF ((SKIPPED_THREAD.OR.(THREAD.AND.IER.NE.0)).AND.
+     &			 BULL_READ.LE.F_NBULL) THEN
+	               CALL READDIR(BULL_READ,IER)
+		       IER = IER - 1
+		       IF (IER.NE.BULL_READ) IER = 0
+		    END IF
+	   	    IF (IER.NE.0.AND.((BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)
+     &			.OR.(BULL_TAG.AND.BTEST(BULL_TAG,1)))) THEN
+		       MSG_NUM = IER
+		       CALL GET_THIS_TAG(FOLDER_NUMBER,IER1,DUMMY,DUMMY)
+		       IF (IER1.EQ.0) THEN
+	                  IF (.NOT.SKIPPED_THREAD) THEN
+		             CALL NEWS_UPDATE_NEWEST_MESSAGE(IER)
+			  ELSE
+			     BULL_READ = BULL_READ + 1
+			  END IF
+			  IER = 0
+	               END IF
+		    ELSE IF (IER.EQ.0) THEN
+		       WRITE (6,'('' No more messages are present.'')')
+		       IF (SKIPPED_THREAD) CALL CLOSE_BULLDIR
+		       GO TO 9999
+	            END IF
+		    IF (IER.NE.0.AND.THREAD.AND..NOT.BTEST(SYSTEM,8)) THEN
+		       SKIPPED_THREAD = .TRUE.
+		       BULL_READ = IER + 1
+		       IER = 0
+		    END IF
+	         END DO
+	      END IF
+	      IF (THREAD) CALL CLOSE_BULLDIR
+	      BULL_READ = IER
+	      IER = IER + 1
+	   ELSE IF (THREAD) THEN
+	      IF (CLI$PRESENT('SINCE')) THEN
+	         IF (IER.EQ.0) THEN
+		    WRITE (6,'('' No messages past specified date.'')')
+		    GO TO 9999
+	         ELSE
+		    BULL_READ = IER - 1
+		    IER = IER + 1
+	         END IF
+	         SINCE = .TRUE.
+	      ELSE IF (CLI$PRESENT('BULLETIN_NUMBER')) THEN
+		 BULL_READ = BULL_READ - 1
+	      ELSE IF (LAST_THREAD_NUMBER.EQ.FOLDER_NUMBER) THEN          
+	         BULL_READ = LAST_THREAD_READ
+	      ELSE
+	         BULL_READ = BULL_POINT - 1
+	      END IF
+	      CALL OPEN_BULLDIR_SHARED
+	      IER = BULL_READ + 1
+	      IER1 = .FALSE.
+	      DO WHILE (.NOT.IER1.AND.IER.EQ.BULL_READ+1.AND.
+     &			BULL_READ.LT.F_NBULL)
+		 BULL_READ = BULL_READ + 1
+	         CALL READDIR(BULL_READ,IER)
+		 IER1 = BTEST(SYSTEM,8)
+	   	 IF (IER1.AND.((BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)
+     &			.OR.(BULL_TAG.AND.BTEST(BULL_TAG,1)))) THEN
+		    CALL GET_THIS_TAG(FOLDER_NUMBER,IER2,DUMMY,DUMMY)
+		    IER1 = IER2.NE.0
+		 END IF
+	      END DO
+	      IF (.NOT.IER1) THEN
+		 WRITE (6,'('' No more messages are present.'')')
+		 GO TO 9999
+	      END IF
+	   END IF
+	END IF
+
+	NEXT = .FALSE.
+	LAST_THREAD = .FALSE.
+	IF (INCMD(:1).EQ.'N'.OR.INCMD.EQ.' ') THEN
+	   NEXT = .TRUE.
+	ELSE IF (INCMD(:4).EQ.'READ') THEN
+	   LAST_THREAD = THREAD
+	   IF (THREAD) THEN
+	      LAST_THREAD_READ = BULL_READ
+	      LAST_THREAD_NUMBER = FOLDER_NUMBER
+	   ELSE
+	      IF (.NOT.SINCE.AND..NOT.NEW
+     &		 .AND..NOT.CLI$PRESENT('BULLETIN_NUMBER')
+     &		 .AND..NOT.CLI$PRESENT('ALL')) NEXT = .TRUE.
+	   END IF
+	END IF
+
+	BULL_NOW = BULL_POINT
+
+	OK = .TRUE.
+50	IF (READ_TAG) THEN
+	   IER = 0
+	   IF ((INCMD(:4).EQ.'BACK'.AND.REMOTE_SET.GE.3).OR.
+     &	       (INCMD(:4).EQ.'LAST'.AND.BTEST(READ_TAG,3))) THEN
+	      IF (BULL_NOW.EQ.0.OR.INCMD(:4).EQ.'LAST') THEN
+		 MSG_NUM = F_NBULL+1
+	      ELSE
+		 MSG_NUM = BULL_NOW
+	      END IF
+	      CALL GET_PREVIOUS_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      IF (IER1.EQ.0) IER = BULL_READ + 1
+	   ELSE IF (INCMD(:4).EQ.'BACK') THEN
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL GET_PREVIOUS_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      CALL CLOSE_BULLDIR
+	      IF (IER1.EQ.0) IER = BULL_READ + 1
+	   ELSE IF (INCMD(:4).EQ.'LAST') THEN
+	      CALL OPEN_BULLDIR_SHARED
+	      IF (BULL_NOW.GT.0) THEN
+		 CALL READDIR(BULL_NOW,IER)
+		 IF (IER.NE.BULL_NOW+1) THEN
+		    BULL_NOW = 0
+		 ELSE
+		    CALL GET_THIS_OR_NEXT_TAG
+     &				   (FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		    IF (IER1.NE.0) BULL_NOW = 0
+		 END IF
+	      END IF
+	      IF (BULL_NOW.EQ.0) THEN
+		 CALL GET_FIRST_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		 IF (IER1.EQ.0) IER = BULL_READ + 1
+	      END IF
+	      DO WHILE (IER1.EQ.0)
+		 CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		 IF (IER1.EQ.0) IER = BULL_READ + 1
+	      END DO
+	      CALL CLOSE_BULLDIR
+	   ELSE IF (INCMD(:4).EQ.'FIRS') THEN
+	      CALL GET_FIRST_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      IF (IER1.EQ.0) IER = BULL_READ + 1
+	   ELSE IF (NEXT.OR.SINCE.OR.NEW) THEN
+	      OLD_NEXT = NEXT
+	      NEXT = .FALSE.
+	      IF (NEW) MSG_NUM = BULL_READ
+	      IF (.NOT.OLD_NEXT) THEN
+		 CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      ELSE
+		 IF (REMOTE_SET.GE.3) THEN
+		    MSG_NUM = BULL_NOW
+		 ELSE IF (BULL_NOW.GT.0) THEN
+		    CALL OPEN_BULLDIR_SHARED
+		    CALL READDIR(BULL_NOW,IER)
+		    CALL CLOSE_BULLDIR
+		 ELSE
+		    MSG_KEY = BULLDIR_HEADER
+		    MSG_NUM = 0
+		 END IF
+		 CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      END IF
+	      NEXT = OLD_NEXT
+	      IF (IER1.EQ.0) THEN
+		 IER = BULL_READ + 1
+	      ELSE
+		 IER = 0
+	      END IF
+	   END IF
+	END IF
+
+	IF (.NOT.SINCE.AND.(.NOT.READ_TAG.OR.(.NOT.NEXT.AND.
+     &		INCMD(:4).NE.'LAST'.AND.INCMD(:4).NE.'BACK'.AND.
+     &		INCMD(:4).NE.'FIRS'))) THEN
+	   IF (BULL_READ.GT.0) THEN		! Valid bulletin number?
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL READDIR(BULL_READ,IER)	! Get bulletin directory entry
+	      IF (IER.NE.BULL_READ+1.AND.REMOTE_SET.GE.3
+     &			   .AND.INCMD(:4).EQ.'READ') THEN
+		 IF (NEW) THEN
+		    NEXT = .TRUE.
+		    CALL READDIR(BULL_READ,IER)
+		 END IF
+	      END IF
+	      IF (REMOTE_SET.LT.3.AND.
+     &			   READ_COUNT.EQ.-1.AND.IER.NE.BULL_READ+1) THEN
+		 READ_COUNT = 0
+		 IF (IER.NE.BULL_READ+1) THEN
+		    CALL READDIR(0,IER)
+		    IF (NBULL.GT.0) THEN
+		       BULL_READ = NBULL
+		       CALL READDIR(BULL_READ,IER)
+		    ELSE
+		       IER = 0
+		    END IF
+		 END IF
+	      ELSE IF (READ_TAG.AND.IER.EQ.BULL_READ+1) THEN
+		 CALL GET_THIS_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		 IF (IER1.NE.0) IER = 0
+	      END IF
+	      CALL CLOSE_BULLDIR
+	   ELSE
+	      IER = -1
+	   END IF
+	END IF
+
+	IF (IER.NE.BULL_READ+1) THEN		! Was bulletin found?
+	   IF (REMOTE_SET.LT.3) THEN
+	      WRITE(6,1030)			! If not, then error out
+	   ELSE
+	      WRITE(6,1040)
+	   END IF
+	   NEXT = .FALSE.
+	   IF (.NOT.OK.AND..NOT.REMOTE_SET) CALL CLOSE_BULLFIL
+	   GO TO 9999
+	END IF
+
+	SAVE_BULL_POINT = BULL_POINT
+	BULL_POINT = BULL_READ			! Update bulletin counter
+
+	IF (OK.OR.REMOTE_SET) CALL OPEN_BULLFIL_SHARED
+
+	IF (BTEST(BULL_USER_CUSTOM,1)
+     &		.AND.(FIRST.OR.NEW.OR.NEXT.OR.INCMD(:4).EQ.'BACK'.OR.
+     &		INCMD(:4).EQ.'LAST'.OR.INCMD(:4).EQ.'FIRS')) THEN
+	   ILEN = LINE_LENGTH + 1
+	   BLOCK_SAVE = BLOCK
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      INFROM = INPUT(7:ILEN)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE
+	      INFROM = FROM
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      INDESCRIP = INPUT(7:ILEN)
+	   ELSE
+	      INDESCRIP = DESCRIP
+	   END IF
+
+	   OK = INCLUDE_MSG(INFROM,INDESCRIP)
+	   OK = OK.AND.(.NOT.THREAD.OR.BTEST(SYSTEM,8)) 
+
+	   IF (.NOT.OK) THEN
+	      BULL_POINT = SAVE_BULL_POINT
+	      BULL_NOW = MSG_NUM
+	      IF (INCMD(:4).EQ.'BACK'.OR.INCMD(:4).EQ.'LAST') THEN
+	         BULL_READ = MSG_NUM - 1
+	      ELSE
+	         BULL_READ = MSG_NUM + 1
+		 IF (INCMD(:4).EQ.'FIRS'.OR.FIRST) NEXT = .TRUE.
+	      END IF
+	      IF (REMOTE_SET) CALL CLOSE_BULLFIL
+	      IF (REMOTE_SET.LT.3.AND..NOT.THREAD) THEN
+		 DIFF = COMPARE_BTIM(MSG_BTIM,
+     &				LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	         IF (DIFF.GT.0) THEN
+	            CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+	         END IF
+	      ELSE IF (.NOT.THREAD) THEN
+	         CALL NEWS_UPDATE_NEWEST_MESSAGE(BULL_NOW)
+              END IF
+	      IF (BULL_READ.GT.F_NBULL.OR.BULL_READ.LT.F_START) THEN
+		 IF (REMOTE_SET.LT.3) THEN
+	            WRITE(6,1030)
+	         ELSE
+		    WRITE(6,1040)
+		 END IF
+		 NEXT = .FALSE.
+	         IF (.NOT.REMOTE_SET) CALL CLOSE_BULLFIL
+		 GO TO 9999
+	      END IF
+	      GO TO 50
+	   END IF
+	   BLOCK = BLOCK_SAVE
+	END IF
+
+	NEXT = .FALSE.
+	IF (REMOTE_SET.LT.3.AND..NOT.THREAD) THEN
+           IF (INCMD(:4).NE.'SEAR'.AND.INCMD(:3).NE.'CUR') THEN
+	      DIFF = COMPARE_BTIM(MSG_BTIM,LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	      IF (DIFF.GT.0) THEN
+	         CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+	      END IF
+	   END IF
+	   IF (BULL_TAG.AND.BTEST(BULL_TAG,1)) CALL ADD_TAG(IER,2)
+	   IF (INCMD.EQ.'LAST'.AND..NOT.READ_TAG) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),F_NEWEST_BTIM)
+	   END IF
+	ELSE
+	   IF (REMOTE_SET.EQ.4) MESSAGE_ID = NEWS_MSGID
+	   IF (BULL_NEWS_TAG) CALL ADD_TAG(IER,2)
+	   IF (.NOT.THREAD.OR.INCMD(:4).NE.'READ') THEN 
+	      IF (INCMD.EQ.'LAST'.AND..NOT.READ_TAG) THEN
+	         CALL NEWS_UPDATE_NEWEST_MESSAGE(F_NBULL)
+	      END IF
+	      IF (INCMD(:4).NE.'SEAR'.AND.INCMD(:3).NE.'CUR') THEN
+	         CALL NEWS_UPDATE_NEWEST_MESSAGE(BULL_READ)
+	      ELSE
+	         CALL NEWS_GET_NEWEST_MESSAGE(IER)
+	         IF (IER.EQ.BULL_READ)
+     &		    CALL NEWS_UPDATE_NEWEST_MESSAGE(BULL_READ)
+	      END IF
+	   END IF
+	END IF
+
+	EDIT = .FALSE.
+
+	PAGE_WIDTH = REAL_PAGE_WIDTH
+
+	IF (INCMD(:1).NE.' '.AND.READIT.EQ.0) THEN
+	   IF (CLI$PRESENT('EDIT')) THEN
+	      OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      IF (IER.NE.0) THEN
+		 CALL ERRSNS(IDUMMY,IER)
+		 CALL SYS_GETMSG(IER)
+		 GO TO 9999
+	      END IF
+	      EDIT = .TRUE.
+	      PAGE_WIDTH = LINE_LENGTH
+	      PAGE = .FALSE.
+	   END IF
+	END IF
+
+	IF (BULL_POINT.GT.F_NBULL) F_NBULL = BULL_POINT
+
+	IF (REMOTE_SET.GE.3) THEN
+	   WRITE (HEADLINE,'(1X,I,'' of '',I,''-'',I)')
+     &				BULL_POINT,F_START,F_NBULL
+	   DO WHILE (INDEX(HEADLINE,'- ').GT.0)
+	      I = INDEX(HEADLINE,'- ')
+	      HEADLINE(I+1:) = HEADLINE(I+2:)
+	   END DO
+	ELSE
+	   WRITE (HEADLINE,'(1X,I,'' of '',I)') BULL_POINT,F_NBULL
+	END IF
+	DO WHILE (INDEX(HEADLINE,'  ').LT.TRIM(HEADLINE))
+	   I = INDEX(HEADLINE,'  ')
+	   HEADLINE(I:) = HEADLINE(I+1:)
+	END DO
+	I = TRIM(HEADLINE)
+	HEADLINE = ' #'//HEADLINE(2:TRIM(HEADLINE))
+	FLEN = TRIM(FOLDER_NAME)
+	HEADLINE(REAL_PAGE_WIDTH-FLEN+1:) = FOLDER_NAME(:FLEN)
+	IF (READIT.GT.0) THEN
+	   WRITE(6,'(A)') '+'//HEADLINE(:TRIM(HEADLINE))
+	ELSE IF (EDIT) THEN
+	   WRITE(3,'(A)') HEADLINE(:TRIM(HEADLINE))
+	ELSE
+	   WRITE(6,'(1X,A)') HEADLINE(:TRIM(HEADLINE))
+	END IF
+
+	END = 1					! Outputted 1 line to screen
+
+	IF (EXDATE(8:11).LT.'1995') THEN
+	   IF (REMOTE_SET.NE.3) THEN
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   (DELETED)'
+	   ELSE
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+	   END IF
+	ELSE IF ((SYSTEM.AND.4).EQ.4) THEN	! Is entry shutdown bulletin?
+	   INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Expires on shutdown'
+	ELSE IF ((SYSTEM.AND.2).EQ.2) THEN	! Is entry permanent bulletin?
+	   INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Permanent'
+	ELSE
+	   INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)//
+     &				'   Expires:   '//EXDATE//' '//EXTIME(:5)
+	END IF
+	IF ((SYSTEM.AND.1).EQ.1) THEN		! System bulletin?
+	   INPUT = INPUT(:TRIM(INPUT))//' / System'
+	END IF
+	IF (EDIT) THEN
+	   WRITE (3,'(A)') INPUT(:TRIM(INPUT))
+	ELSE
+	   WRITE (6,'(1X,A)') INPUT(:TRIM(INPUT))
+	END IF
+
+	END = END + 1
+
+	LINE_OFFSET = 0
+	CHAR_OFFSET = 0
+	ILEN = LINE_LENGTH + 1
+	CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: '
+     &	   .AND..NOT.BTEST(SYSTEM,4)) THEN
+	   INPUT = 'From:   '//INPUT(7:)
+	   DO WHILE (TRIM(INPUT).GT.0)
+	      I = MIN(PAGE_WIDTH,TRIM(INPUT))
+	      IF (EDIT) THEN
+		 WRITE(3,'(A)') INPUT(:I)
+	      ELSE
+		 WRITE(6,'(1X,A)') INPUT(:I)
+	      END IF
+	      INPUT = INPUT(I+1:)
+	      END = END + 1
+	   END DO
+	   LINE_OFFSET = 1
+	ELSE
+	   IF (EDIT) THEN
+	      WRITE(3,'(''From:   '',A)') FROM
+	   ELSE
+	      WRITE(6,'('' From:   '',A)') FROM
+	   END IF
+	   END = END + 1
+	END IF
+	IF (INPUT(:6).NE.'Subj: ') THEN
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	END IF
+	LEN_TEMP = ILEN
+	CALL CONVERT_TABS(INPUT,LEN_TEMP)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	   INPUT = 'Subj:   '//INPUT(7:)
+	   DO WHILE (TRIM(INPUT).GT.0)
+	      I = MIN(PAGE_WIDTH,TRIM(INPUT))
+	      IF (EDIT) THEN
+		 WRITE(3,'(A)') INPUT(:I)
+	      ELSE
+		 WRITE(6,'(1X,A)') INPUT(:I)
+	      END IF
+	      INPUT = INPUT(I+1:)
+	      END = END + 1
+	   END DO
+	   LINE_OFFSET = LINE_OFFSET + 1
+	   IF (EDIT) WRITE(3,'(1X)')
+	ELSE
+	   END = END + 1
+	   IF (EDIT) THEN
+	      WRITE(3,'(''Subj:   '',A)') DESCRIP(:TRIM(DESCRIP))
+	      WRITE(3,'(1X,/,A)') INPUT(:LEN_TEMP)
+	   ELSE
+	      WRITE(6,'('' Subj:   '',A)') DESCRIP(:TRIM(DESCRIP))
+	      IF (LINE_OFFSET.EQ.1) THEN
+		 CHAR_OFFSET = 1 - PAGE_WIDTH
+		 LINE_OFFSET = 2
+		 IF (ROTC) CALL CONVERT_ROTC(INPUT,LEN_TEMP)
+	      END IF
+	   END IF
+	END IF
+	IF (LINE_OFFSET.EQ.0) ILEN = LINE_LENGTH + 1
+	CALL CLOSE_BULLFIL			! End of bulletin file read
+
+	IF (EDIT) GO TO 200
+
+	WRITE(6,'(1X)')
+
+	IF (READIT.GT.0) WRITE(6,'(1X)')
+	END = END + 1
+C
+C  Each page of the bulletin is buffered into temporary memory storage before
+C  being outputted to the terminal.  This is to be able to quickly close the
+C  bulletin file, and to avoid the possibility of the user holding the screen,
+C  and thus causing the bulletin file to stay open.  The temporary memory
+C  is structured as a linked-list queue, where SCRATCH_B1 points to the header
+C  of the queue.  See BULLSUBS.FOR for more description of the queue.
+C
+
+	IF (SCRATCH_B1.NE.0) THEN		! Is queue empty?
+	   SCRATCH_B = SCRATCH_B1		! No, set queue pointer to head
+	ELSE					! Else if queue is empty
+	   CALL INIT_QUEUE(SCRATCH_B,INPUT)
+	   SCRATCH_B1 = SCRATCH_B		! Init header pointer
+	END IF
+
+	READ_ALREADY = 0			! Number of lines already read
+						! from record.
+	IF (READ_COUNT.EQ.-2) THEN		! Just output header first read
+	   READ_COUNT = BLOCK
+	   GO TO 9999
+	ELSE
+	   READ_COUNT = BLOCK			! Init bulletin record counter
+	END IF
+
+	GO TO 200
+
+100	IF (READIT.EQ.0) THEN 			! If not 1st page of READ
+	   WRITE(6,'(1X,A,/)') HEADLINE(:TRIM(HEADLINE)) ! Output header info
+	   END = END + 2			! Increase display counter
+	END IF
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+
+200	DISPLAY = 0
+	IF (READIT.GT.0) END = END - 2		! /READ can output 2 more lines
+
+	CALL OPEN_BULLFIL_SHARED		! Get bulletin file
+	MORE_LINES = .TRUE.
+	DO WHILE (ILEN.GT.0.AND.MORE_LINES)
+	   IF (CHAR_OFFSET.EQ.0) THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      LINE_OFFSET = LINE_OFFSET + 1
+	   END IF
+	   IF (ILEN.LT.0) THEN		! Error, couldn't read record
+	      ILEN = 0			! Fake end of reading file
+	      MORE_LINES = .FALSE.
+	   ELSE IF (ILEN.GT.0) THEN
+	      IF (EDIT) THEN
+		 WRITE(3,'(A)') INPUT(:ILEN)
+	      ELSE IF (CHAR_OFFSET.EQ.0) THEN
+		 LEN_TEMP = ILEN
+		 CALL CONVERT_TABS(INPUT,LEN_TEMP)
+		 IF (ROTC) CALL CONVERT_ROTC(INPUT,LEN_TEMP)
+		 IF (LEN_TEMP.GT.PAGE_WIDTH) THEN
+		    CHAR_OFFSET = 1
+		    BUFFER = INPUT(:PAGE_WIDTH)
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER)
+		 ELSE
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,INPUT)
+		 END IF
+	      ELSE
+		 CHAR_OFFSET = CHAR_OFFSET + PAGE_WIDTH
+		 IF (LEN_TEMP.LE.CHAR_OFFSET+PAGE_WIDTH-1) THEN
+		    BUFFER = INPUT(CHAR_OFFSET:LEN_TEMP)
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER)
+		    CHAR_OFFSET = 0
+		 ELSE
+		    BUFFER = INPUT(CHAR_OFFSET:CHAR_OFFSET+PAGE_WIDTH-1)
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER)
+		 END IF
+	      END IF
+	      DISPLAY = DISPLAY + 1
+	      IF ((DISPLAY.EQ.PAGE_LENGTH-END-4).AND.PAGE) THEN
+		 MORE_LINES = .FALSE.
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFIL			! End of bulletin file read
+
+	IF (EDIT) THEN
+	   CLOSE (UNIT=3)
+	   CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	   READ_COUNT = 0			! init bulletin record counter
+	   GO TO 9999
+	END IF
+
+C
+C  Bulletin page is now in temporary memory, so output to terminal.
+C  Note that if this is a /READ, the first line will have problems with
+C  the usual FORMAT statement.  It will cause a blank line to be outputted
+C  at the top of the screen.  This is because of the input QIO at the
+C  end of the previous page.  The output gets confused and thinks it must
+C  end the previous line.  To prevent that, the first line of a new page
+C  in a /READ must use a different FORMAT statement to surpress the CR/LF.
+C
+
+	SCRATCH_B = SCRATCH_B1			! Reinit queue pointer to head
+	DO I=1,DISPLAY				! Output page to terminal
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER) ! Get queue record
+	   IF (I.EQ.1.AND.READIT.GT.0) THEN
+	      WRITE(6,'(A)') '+'//BUFFER(:TRIM(BUFFER))	 ! (See above comments)
+	   ELSE
+	      WRITE(6,'(1X,A)') BUFFER(:TRIM(BUFFER))
+	   END IF
+	END DO
+
+	IF (ILEN.EQ.0) THEN			! End of message?
+	   READ_COUNT = 0			! init bulletin record counter
+	ELSE	! Possibly end of message since end of page could be last line
+	   CALL TEST_MORE_RECORDS(BLOCK,LENGTH,IREC)
+	   IF (IREC.EQ.0) THEN			! Last record?
+	      CALL TEST_MORE_LINES(ILEN)	! More lines to read?
+	      IF (ILEN.GT.0) THEN		! Yes, there are still more
+		 IF (READIT.EQ.0) WRITE(6,1070)	! say there is more of bulletin
+	      ELSE				! Yes, last line anyway
+		 READ_COUNT = 0			! init bulletin record counter
+	      END IF
+	   ELSE IF (READIT.EQ.0) THEN		! Not last record so
+	      WRITE(6,1070)			! say there is more of bulletin
+	   END IF
+	END IF
+
+9999	POSTTIME = .FALSE.
+	IF (KILL) BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,3)
+	RETURN
+
+1030	FORMAT(' No more messages.')
+1040	FORMAT(' Message not found.')
+1070	FORMAT(1X,/,' Press RETURN for more...',/)
+
+2000	FORMAT(A)
+
+	END
+
+
+
+
+
+	SUBROUTINE CONVERT_ROTC(INPUT,LEN_TEMP)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER INPUT*(*)
+
+	DO I=1,LEN_TEMP
+	   IF (INPUT(I:I).GE.'A'.AND.INPUT(I:I).LE.'Z') THEN
+	      INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) - 13)
+	      IF (INPUT(I:I).LT.'A')
+     &			INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) + 26)
+	   ELSE IF (INPUT(I:I).GE.'a'.AND.INPUT(I:I).LE.'z') THEN
+	      INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) - 13)
+	      IF (INPUT(I:I).LT.'a')
+     &			INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) + 26)
+
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+
+
+	SUBROUTINE READNEW(REDO)
+C
+C  SUBROUTINE READNEW
+C
+C  FUNCTION: Displays new non-system bulletins with prompts between bulletins.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /READ_DISPLAY/ LINE_OFFSET
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER INREAD4*4,FILE_DEF*80,NUMREAD*8
+	CHARACTER INREAD*1
+	EQUIVALENCE (INREAD4,INREAD)
+
+	DATA LEN_FILE_DEF /0/, INREAD/0/
+
+	LOGICAL SLOW,SLOW_TERMINAL
+
+	FIRST_MESSAGE = BULL_POINT
+
+	IF (ICHAR(INREAD).EQ.0) THEN	! If calling READNEW for first time
+	   SLOW = SLOW_TERMINAL()	! Check baud rate of terminal
+	END IF				! to avoid gobs of output
+
+	LEN_P = 0			! Tells read subroutine there is
+					! no bulletin parameter
+
+1	WRITE(6,1000)			! Ask if want to read new bulletins
+
+	CALL GET_INPUT_NUM(NUMREAD,NLEN)	! Get input
+	CALL STR$UPCASE(NUMREAD,NUMREAD)	! Make input upper case
+	READ (NUMREAD,'(I<NLEN>)',IOSTAT=IER) TEMP_READ
+	IF (IER.NE.0) THEN
+	   INREAD = NUMREAD(:1)
+	   IF (INREAD.EQ.'N'.OR.INREAD.EQ.'Q'.OR.INREAD.EQ.'E') THEN
+	      IF (INREAD.EQ.'Q') THEN
+		 WRITE (6,'(''+uit'',$)')
+	      ELSE IF (INREAD.EQ.'E') THEN
+		 WRITE (6,'(''+xit'',$)')
+		 DO I=1,FLONG			! Just show SYSTEM folders
+		    NEW_MSG(I) = NEW_MSG(I).AND.SYSTEM_FLAG(I)
+		 END DO
+		 DO I=1,FLONG	! Test for new messages in SYSTEM folders
+		    IF (NEW_MSG(I).NE.0) RETURN
+		 END DO
+		 CALL EXIT
+	      ELSE
+		 WRITE (6,'(''+o'',$)')
+	      END IF
+	      RETURN	! If NO, exit
+	      		! Include QUIT to be consistent with next question
+	   ELSE
+	      CALL LIB$ERASE_PAGE(1,1)
+	   END IF
+	END IF
+
+3	IF (TEMP_READ.GT.0) THEN
+	   IF (TEMP_READ.LT.FIRST_MESSAGE+1.OR.TEMP_READ.GT.NBULL) THEN
+	      WRITE (6,'('' ERROR: Specified new message not found.'')')
+	      GO TO 1
+	   ELSE
+	      BULL_POINT = TEMP_READ - 1
+	   END IF
+	END IF
+
+	READ_COUNT = 0				! Initialize display pointer
+
+5	CALL READ_MSG(READ_COUNT,BULL_POINT+1)	! Read next bulletin
+	BULL_POINT_READ = BULL_POINT
+	IF (READ_COUNT.EQ.0) THEN		! Is full bulletin displayed?
+	   CALL OPEN_BULLDIR_SHARED		! If so, see if more new bulls
+10	   CALL READDIR(BULL_POINT+1,IER_POINT)
+	   IF ((IER_POINT.EQ.BULL_POINT+2).AND.	! If system bulletin (and system
+     &	       (SYSTEM.AND.BTEST(FOLDER_FLAG,2))) THEN	! folder) then skip it.
+	      BULL_POINT = BULL_POINT + 1
+	      GO TO 10
+	   END IF
+	   CALL CLOSE_BULLDIR
+	END IF
+
+	GO TO 12
+
+11	IF (READ_COUNT.GT.0) THEN
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL OPEN_BULLFIL_SHARED
+	   CALL READDIR(BULL_POINT,IER)
+	   ILEN = LINE_LENGTH+1
+	   DO I=1,LINE_OFFSET
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END DO
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	END IF
+
+	BULL_POINT = BULL_POINT_SAVE
+	LENGTH = LENGTH_SAVE
+	BLOCK = BLOCK_SAVE
+
+12	IF (READ_COUNT.EQ.0) THEN		! Prompt user in between
+	   WRITE(6,1020)			! full screens or end of bull.
+	ELSE
+	   WRITE(6,1030)
+	END IF
+
+	CALL GET_INPUT_NOECHO(INREAD)
+	CALL STR$UPCASE(INREAD,INREAD)	! Convert input to upper case
+
+	BLOCK_SAVE = BLOCK
+	LENGTH_SAVE = LENGTH
+	BULL_POINT_SAVE = BULL_POINT
+
+	IF (INREAD.EQ.'Q') THEN		! If Q , then QUIT
+	   WRITE (6,'(''+Quit'',$)')
+	   RETURN
+	ELSE IF (INREAD.EQ.'D') THEN	! If D , then redisplay directory
+	   WRITE (6,'(''+Dir'',$)')
+	   REDO = .TRUE.
+	   RETURN
+	ELSE IF (INREAD.EQ.'F'.AND..NOT.CAPTIVE(1)) THEN
+	   				! If F then copy bulletin to file
+	   WRITE (6,'(''+ '')')		! Move cursor from end of prompt line
+	   				! to beginning of next line.
+	   IF (LEN_FILE_DEF.EQ.0) THEN
+	      CALL LIB$SYS_TRNLOG('SYS$LOGIN',ILEN,FILE_DEF)
+	      IER = LIB$FIND_FILE(FILE_DEF//'BULL.DIR',
+     &			BULL_PARAMETER,CONTEXT)
+	      IF (IER) THEN
+		 FILE_DEF = BULL_PARAMETER(:ILEN-1)//'.BULL]'
+		 LEN_FILE_DEF = ILEN + 5
+	      ELSE
+		 FILE_DEF = 'SYS$LOGIN:'
+		 LEN_FILE_DEF = 10
+	      END IF
+	   END IF
+
+	   LEN_FOLDER = TRIM(FOLDER)
+	   CALL GET_INPUT_PROMPT(BULL_PARAMETER,LEN_P,
+     &		'Name of file? (Default='//FILE_DEF(:LEN_FILE_DEF)//
+     &		FOLDER(:LEN_FOLDER)//'.LIS) ')
+
+	   IF (LEN_P.EQ.0) THEN
+	      BULL_PARAMETER = FILE_DEF(:LEN_FILE_DEF)//FOLDER(:LEN_FOLDER)
+     &			//'.LIS'
+	      LEN_P = LEN_FILE_DEF + LEN_FOLDER + 4
+	   ELSE
+	      IER = LIB$SYS_TRNLOG(BULL_PARAMETER(:LEN_P),ILEN,INPUT)
+	      IF (IER.NE.1.AND.INDEX(BULL_PARAMETER(:LEN_P),':').EQ.0
+     &		  .AND.INDEX(BULL_PARAMETER(:LEN_P),'[').EQ.0) THEN
+		 BULL_PARAMETER = FILE_DEF(:LEN_FILE_DEF)//
+     &				BULL_PARAMETER(:LEN_P)
+		 LEN_P = LEN_P + LEN_FILE_DEF
+	      END IF
+	   END IF
+
+	   BULL_POINT = BULL_POINT_READ
+	   INCMD = 'FILE '//BULL_PARAMETER(:LEN_P)
+	   IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	   CALL FILE(0,.TRUE.,.FALSE.)
+	   GO TO 11
+	ELSE IF (INREAD.EQ.'P') THEN
+	   WRITE (6,'(''+P'',$)')
+	   BULL_POINT = BULL_POINT_READ
+	   IF (REMOTE_SET.GE.3.OR.
+     &	       INDEX(FOLDER_DESCRIP,'<').GT.0) THEN
+	      WRITE(6,1040)
+	      CALL GET_INPUT_NOECHO(INREAD)
+	      CALL STR$UPCASE(INREAD,INREAD)
+	      IF (INREAD.EQ.'P') THEN
+		 WRITE (6,'(''+P'',$)')
+		 INCMD = 'REPLY'
+	      ELSE IF (INREAD.EQ.'U') THEN
+		 WRITE (6,'(''+U'',$)')
+		 INCMD = 'RESPOND'
+	      ELSE IF (INREAD.EQ.'B') THEN
+		 WRITE (6,'(''+B'',$)')
+		 INCMD = 'RESPOND/LIST'
+	      ELSE
+		 GO TO 11
+	      END IF
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL RESPOND
+	   ELSE IF (READ_ONLY) THEN
+	      WRITE (6,'(
+     &		 '' ERROR: You do not write access to this folder.'')')
+	   ELSE
+	      INCMD = 'REPLY'
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL REPLY
+	   END IF
+	   GO TO 11
+	ELSE IF (INREAD.EQ.'N'.AND.READ_COUNT.GT.0) THEN
+	   			! If NEXT and last bulletins not finished
+	   READ_COUNT = 0			! Reset read bulletin counter
+	   CALL OPEN_BULLDIR_SHARED		! Look for NEXT bulletin
+20	   CALL READDIR(BULL_POINT+1,IER)
+	   IF (IER.NE.BULL_POINT+2) THEN	! If no NEXT bulletin
+	      CALL CLOSE_BULLDIR		! Exit
+	      WRITE(6,1010)
+	      RETURN
+	   ELSE IF (SYSTEM.AND.BTEST(FOLDER_FLAG,2)) THEN
+	      BULL_POINT = BULL_POINT + 1	! If SYSTEM bulletin, skip it
+	      GO TO 20			! Look for more bulletins
+	   END IF
+	   CALL CLOSE_BULLDIR
+	ELSE IF (INREAD.EQ.'R') THEN
+	   WRITE (6,'(''+Read'')')
+	   WRITE (6,'('' Enter message number: '',$)')
+	   CALL GET_INPUT_NUM(NUMREAD,NLEN)	! Get input
+	   CALL STR$UPCASE(NUMREAD,NUMREAD)	! Make input upper case
+	   READ (NUMREAD,'(I<NLEN>)',IOSTAT=IER) TEMP_READ
+	   IF (IER.NE.0.OR.TEMP_READ.LE.0) THEN
+	      WRITE (6,'('' ERROR: Invalid message number specified.'')')
+	      GO TO 12
+	   ELSE
+	      GO TO 3
+	   END IF
+	ELSE IF (IER_POINT.NE.BULL_POINT+2.AND.READ_COUNT.EQ.0) THEN
+	   WRITE(6,1010)
+	   RETURN
+	END IF
+	IF (READ_COUNT.EQ.0.AND.SLOW) READ_COUNT = -2
+	GO TO 5
+
+1000	FORMAT(' Read messages? Type N(No),E(Exit),message',
+     &	 ' number, or any other key for yes: ',$)
+1010	FORMAT(' No more messages.')
+1020	FORMAT(1X,<PAGE_WIDTH>('-'),/,' Type Q(Quit),F(File),D(Dir),',
+     &	'R(Read msg #),P(Reply) or other for next message: ',$)
+1030	FORMAT(1X,<PAGE_WIDTH>('-'),/,' Type Q(Quit),F(File),N(Next),',
+     &	'D(Dir),R(Read msg #),P(Reply) or other for MORE: ',$)
+1040	FORMAT(' Type P to post reply, U to reply to user,',
+     &	' B to do both, or other to quit: ',$)
+
+	END
+
+
+
+
+	SUBROUTINE SET_DEFAULT_EXPIRE
+C
+C  SUBROUTINE SET_DEFAULT_EXPIRE
+C
+C  FUNCTION: Sets default expiration date.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER EXPIRE*3
+
+	IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   IER = CLI$GET_VALUE('DEFAULT_EXPIRE',EXPIRE,EX_LEN)
+	   IF (EX_LEN.GT.3) EX_LEN = 3
+	   READ (EXPIRE,'(I<EX_LEN>)') TEMP
+
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   IF (TEMP.GT.BBEXPIRE_LIMIT.AND..NOT.SETPRV_PRIV()) THEN
+	      WRITE (6,'('' ERROR: Expiration cannot be > '',
+     &			I3,'' days.'')') BBEXPIRE_LIMIT
+	   ELSE IF (TEMP.LT.-1) THEN
+	      WRITE (6,'('' ERROR: Expiration must be > -1.'')')
+	   ELSE
+	      FOLDER_BBEXPIRE = TEMP
+	      WRITE (6,'('' Default expiration modified.'')')
+	   END IF
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLFOLDER
+	ELSE
+	   WRITE (6,'('' You are not authorized to set expiration.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION NEWS_FEED()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	NEWS_FEED = .FALSE.
+
+	SLIST = INDEX(FOLDER_DESCRIP,'<')
+	IF (SLIST.GT.0) THEN
+	   I = SLIST + 1
+	   FLEN = TRIM(FOLDER_DESCRIP)
+	   DO WHILE (I.LE.FLEN)
+	      IF (FOLDER_DESCRIP(I:I).EQ.'>') THEN
+C		 IF (INDEX(FOLDER_DESCRIP(SLIST:I),'.').GT.0)
+C     &		    NEWS_FEED = .TRUE.
+		 NEWS_FEED = .TRUE.
+		 RETURN
+	      ELSE IF ((FOLDER_DESCRIP(I:I).LT.'A'.OR.
+     &		  FOLDER_DESCRIP(I:I).GT.'Z').AND.
+     &		  FOLDER_DESCRIP(I:I).NE.':'.AND.
+     &		  FOLDER_DESCRIP(I:I).NE.'@'.AND.
+     &		  FOLDER_DESCRIP(I:I).NE.'%') THEN
+		 I = I + 1
+	      ELSE
+		 I = FLEN + 2
+	      END IF
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION MAIL_POST()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	IF (NEWS_FEED()) THEN
+	   MAIL_POST = INDEX(FOLDER_DESCRIP,'[').GT.0
+	ELSE
+	   MAIL_POST = INDEX(FOLDER_DESCRIP,'<').GT.0
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin10.for b/decus/vmslt00a/bulletin/bulletin10.for
new file mode 100755
index 0000000000000000000000000000000000000000..84139623297e0bb80ba6bd6fd86281a7637650cb
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin10.for
@@ -0,0 +1,4124 @@
+C
+C  BULLETIN10.FOR, Version 2/27/97
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	INTEGER FUNCTION NEWS_READ()
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	PARAMETER CR = CHAR(13), LF = CHAR(10)
+
+	COMMON /NEWS_INIT/ END_READ
+
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+
+	NEWS_READ = 1
+
+	IF (END_READ.EQ.0) THEN
+	   IER = NEWS_READ_PACKET(BUFFER(:1024))
+	   IF (IER.LE.0) THEN
+	      CALL NEWS_LOGOUT
+	      NEWS_READ = 0
+	      RETURN
+	   END IF
+	   START_READ = 1
+	   END_READ = IER
+	END IF
+
+	IF (END_READ.EQ.0) THEN
+	   NEWS_READ = 0
+	   RETURN
+	END IF
+
+	DO WHILE (NEWS_READ.GT.0)
+	   LAST_LF_SEEN = LF_SEEN
+	   LAST_REAL_LF_SEEN = REAL_LF_SEEN
+	   END_LINE = INDEX(BUFFER(START_READ:END_READ),LF)
+	   CR_SEEN = INDEX(BUFFER(START_READ:END_READ),CR)
+	   IF (CR_SEEN.GT.0) THEN
+	      IF (END_LINE.GT.0) THEN
+		 IF (CR_SEEN.EQ.END_LINE-2.AND.BUFFER(START_READ+CR_SEEN:
+     &		     START_READ+CR_SEEN).EQ.CR) CR_SEEN = CR_SEEN + 1
+	      ELSE
+		 IF (START_READ+CR_SEEN.EQ.END_READ.AND.
+     &		     BUFFER(END_READ:END_READ).EQ.CR) CR_SEEN = 0
+	      END IF
+	   END IF
+	   IF ((END_LINE.EQ.0.AND.CR_SEEN+START_READ-1.LT.END_READ.AND.
+     &			CR_SEEN.GT.0).OR.CR_SEEN.LT.END_LINE-1) THEN
+	      END_LINE = CR_SEEN
+	      CR_SEEN = 1
+	   ELSE
+	      CR_SEEN = 0
+	   END IF
+	   LF_SEEN = END_LINE.GT.0
+	   IF (END_LINE.GT.257-CR_SEEN.OR.
+     &	       (END_LINE.EQ.0.AND.END_READ-START_READ.GE.254)) THEN
+	      END_LINE = 255
+	      IF (.NOT.HEADER_SEEN) END_LINE = 254
+	   END IF
+	   REAL_LF_SEEN = INDEX(BUFFER(START_READ:END_READ),LF).LE.END_LINE
+	   IF (END_LINE.GT.0) THEN
+	      SB = START_READ
+	      END_LINE = END_LINE + SB - 1
+	      EB = END_LINE
+	      IF (BUFFER(EB:EB).EQ.LF) EB = EB - 1
+	      IF (BUFFER(EB:EB).EQ.CR) EB = EB - 1
+	      IF (BUFFER(EB:EB).EQ.CR) EB = EB - 1
+	      IF (END_LINE.LT.END_READ) THEN
+		 START_READ = END_LINE + 1
+	      ELSE
+		 END_READ = 0
+	      END IF
+	      IF (EB.GT.0.OR.LAST_LF_SEEN) RETURN
+	   ELSE
+	      BUFFER = BUFFER(START_READ:END_READ)
+	      END_READ = END_READ - START_READ + 1
+	      IER = NEWS_READ_PACKET(BUFFER(END_READ+1:END_READ+1024))
+	      IF (IER.LE.0) THEN
+		 NEWS_READ = 0
+		 RETURN
+	      ELSE
+		 START_READ = 1
+		 END_READ = END_READ + IER
+	      END IF
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION NEWS_WRITE(WRITE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	PARAMETER CR = CHAR(13), LF = CHAR(10)
+
+	COMMON /NEWS_INIT/ END_READ
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LOCALPOST/ LOCAL_POST
+
+	CHARACTER*(*) WRITE
+
+	LOGICAL TRY_RECONNECT/.FALSE./
+
+	IF (LOCAL_POST) THEN
+	   WRITE (8,'(A)') WRITE(:MIN(LEN(WRITE),256))
+	   DO I=1,LEN(INPUT),255
+	      CALL COMPRESS(WRITE,INPUT,L)
+	      LENGTH = LENGTH + MAX(1,L) + 1
+	   END DO
+	   NEWS_WRITE = .TRUE.
+	   RETURN
+	END IF
+
+	END_READ = 0
+
+	IF (WRITE.EQ.' ') THEN
+	   NEWS_WRITE = NEWS_WRITE_PACKET(CR//LF)
+	ELSE
+	   NEWS_WRITE = NEWS_WRITE_PACKET(WRITE//CR//LF)
+	END IF
+
+	IF (.NOT.NEWS_WRITE.AND..NOT.TRY_RECONNECT) THEN
+	   TRY_RECONNECT = .TRUE.
+	   NEWS_WRITE = NEWS_RECONNECT(WRITE)
+	   TRY_RECONNECT = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	LOGICAL FUNCTION NEWS_RECONNECT(WRITE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*(*) WRITE
+
+	CHARACTER*8 NUMBER
+
+	CHARACTER*(FOLDER_RECORD) FOLDER2_COM
+
+	NEWS_RECONNECT = .FALSE.
+
+	CALL NEWS_LOGOUT
+
+	IF (.NOT.NEWS_LOGIN()) RETURN
+
+	IF (FOLDER(:1).GE.'a'.AND.FOLDER(:1).LE.'z') THEN
+	   FOLDER2_COM = FOLDER1_COM
+	   FOLDER1 = FOLDER
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP
+	   CALL NEWS_GROUP(IER)
+	   IF (IER.NE.0) RETURN
+	   FOLDER1_COM = FOLDER2_COM
+
+	   IF (.NOT.OTS$CVT_L_TI(BULL_POINT+1,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	END IF
+
+	IF (.NOT.NEWS_WRITE(WRITE)) RETURN
+
+	NEWS_RECONNECT = .TRUE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_LOGOUT
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_CONNECTED/ NEWS_CONNECTED
+
+	CALL NEWS_DISCONNECT
+	NEWS_CONNECTED = .FALSE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_DELETE(SBULL,IMMEDIATE,SUBJ,I,FOLDER1_COM,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /HEADER/ HEADER
+
+	CHARACTER*(*) SUBJ,FOLDER1_COM
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE(REMOTE_UNIT,'(4A)',IOSTAT=IER)
+     &			 4,SBULL,IMMEDIATE,SUBJ
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	ELSE IF (REMOTE_SET.GE.3) THEN
+	   IF (TEST_NEWS_OWNER().OR.SETPRV_PRIV()) THEN
+	      IF (REMOTE_SET.EQ.4) THEN
+		 HEADER_SAVE = HEADER
+		 HEADER = .TRUE.
+		 CALL OPEN_BULLFIL_SHARED
+		 ILEN = LINE_LENGTH + 1
+		 DO WHILE (ILEN.GT.0)
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    IF (INPUT(:11).EQ.'Message-ID:') THEN
+		       MESSAGE_ID = INPUT(14:ILEN-1)
+		       ILEN = 0
+		    END IF
+		 END DO
+		 CALL CLOSE_BULLFIL
+		 HEADER = HEADER_SAVE
+	      END IF
+	      CALL NEWS_POST('cancel',0,IER,SUBJ)
+	   ELSE IF (REMOTE_SET.EQ.3) THEN
+	      WRITE (6,'('' ERROR: Not owner of message.'')')
+	   END IF
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_NEWS_OWNER()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	CHARACTER*12 HIGHFROM
+
+	CALL STR$UPCASE(HIGHFROM,FROM)
+	IF (LPATH.EQ.0) CALL GET_PATHNAME
+	TEST_NEWS_OWNER = FROM.EQ.USERNAME.OR.
+     &	    (HIGHFROM.EQ.USERNAME.AND.
+     &	    MESSAGE_ID(FIRST_INDEX(MESSAGE_ID,'@%'):
+     &	    TRIM(MESSAGE_ID)).EQ.
+     &	    PATHNAME(FIRST_INDEX(PATHNAME,'@%'):LPATH))
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION FIRST_INDEX(INPUT,FIND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,FIND
+
+	FIRST_INDEX = 0
+
+	DO I=1,LEN(FIND)
+	   J = INDEX(INPUT,FIND(I:I))
+	   IF (J.GT.0.AND.(FIRST_INDEX.EQ.0.OR.J.LT.FIRST_INDEX))
+     &		FIRST_INDEX = J
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_DIRECTORY_COMMAND(START,END,REVERSE,ALL_DIR,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /XHDR/ XHDR
+	LOGICAL XHDR /.FALSE./
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*8 NUMBER,NUMBER1
+
+	CHARACTER*1024 TEMP
+
+	DATA QXHDR1 /0/
+
+	IF (XHDR) THEN
+	   IF (QXHDR1.NE.0) THEN                ! Is queue empty?
+	      QXHDR = QXHDR1            ! No, set queue pointer to head
+	   ELSE                         ! Else if queue is empty
+	      CALL INIT_QUEUE(QXHDR,TEMP)
+	      QXHDR1 = QXHDR            ! Init header pointer
+	   END IF
+	END IF
+
+	SYSTEM = 0
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   IF (REVERSE) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER) 13,END,START
+	   ELSE
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER) 13,START,END
+	   END IF
+	ELSE
+	   IER = 2
+	   NUMDIR = END - START + 1
+	   IF (START.LT.F_START) THEN
+	      START = F_START
+	      END = START + NUMDIR - 1
+	   END IF
+	END IF
+
+	STAT = .TRUE.
+
+	IF (REMOTE_SET.EQ.3.AND.XHDR) THEN
+	   STAT = .FALSE.
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.OTS$CVT_L_TI(END,NUMBER1,,,)) RETURN
+	   DO WHILE (NUMBER1(1:1).EQ.' ')
+	      NUMBER1 = NUMBER1(2:)
+	   END DO
+	   NUMDIR1 = 0
+	   DO WHILE (NUMDIR1.LT.NUMDIR)
+	      IF (.NOT.NEWS_WRITE('XHDR DATE '//NUMBER//'-'//NUMBER1))
+     &								RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (BUFFER(:2).NE.'22') THEN
+		 IF (NUMDIR1.EQ.0) THEN
+		    IER = 0
+		    END = START - 1
+		    RETURN
+		 ELSE
+		    NUMDIR = NUMDIR1
+		 END IF
+	      ELSE
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IF (NUMDIR1.EQ.0.AND.BUFFER(SB:EB).NE.'.') THEN
+		    IF (.NOT.OTS$CVT_TI_L(BUFFER(SB:INDEX(BUFFER(SB:EB),' ')
+     &			+SB-2),START,,%VAL(1))) RETURN
+		 END IF
+		 DO WHILE (BUFFER(SB:EB).NE.'.')
+		    IF (NUMDIR1.LT.NUMDIR) THEN
+		       NUMDIR1 = NUMDIR1 + 1
+		       TEMP = BUFFER(SB:EB)
+		       CALL WRITE_QUEUE(%VAL(QXHDR),QXHDR,TEMP)
+		    END IF
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+		 IF (NUMDIR1.EQ.0) THEN
+		    IF (START.LE.F_START) THEN
+		       IF (END.GE.F_NBULL) RETURN
+		       START = MIN(F_NBULL,END+1)
+		    ELSE
+		       START = MAX(F_START,START-NUMDIR)
+		    END IF
+		    END = START + NUMDIR - 1
+		    IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+		    IF (.NOT.OTS$CVT_L_TI(END,NUMBER1,,,)) RETURN
+		    DO WHILE (NUMBER1(1:1).EQ.' ')
+		       NUMBER1 = NUMBER1(2:)
+		    END DO
+		 ELSE IF (NUMDIR1.LT.NUMDIR) THEN
+		    STAT = .TRUE.
+		    IF (.NOT.NEWS_WRITE('STAT '//TEMP(:INDEX(TEMP,' ')-1)))
+     &								 RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		    IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		    IF (BUFFER(:2).NE.'22') THEN
+		       NUMDIR = NUMDIR1
+		    ELSE
+		       NUMBER = BUFFER(SB+4:INDEX(BUFFER(SB+4:),' ')+SB+2)
+		       IF (.NOT.OTS$CVT_TI_L(NUMBER,
+     &						MSG_NUM,,%VAL(1))) RETURN
+		       DO WHILE (NUMBER(LEN(NUMBER):).EQ.' ')
+			  NUMBER = ' '//NUMBER(1:)
+		       END DO
+		       MSG_NUM = MSG_NUM + (NUMDIR - NUMDIR1) - 1
+		       IF (.NOT.OTS$CVT_L_TI(MSG_NUM,NUMBER1,,,)) RETURN
+		       DO WHILE (NUMBER1(1:1).EQ.' ')
+			  NUMBER1 = NUMBER1(2:)
+		       END DO
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   CALL OTS$CVT_L_TI(START,NUMBER,,,)
+	   NUMBER1 = TEMP(:INDEX(TEMP,' ')-1)
+	   END = START + NUMDIR - 1
+	   DO I=1,2
+	      IF (I.EQ.1) THEN
+		 IF (.NOT.NEWS_WRITE
+     &		  ('XHDR SUBJECT '//NUMBER//'-'//NUMBER1)) RETURN
+	      ELSE
+		 IF (.NOT.NEWS_WRITE
+     &		  ('XHDR FROM '//NUMBER//'-'//NUMBER1)) RETURN
+	      END IF
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (BUFFER(:2).EQ.'22') THEN
+		 QXHDR = QXHDR1
+		 IF (.NOT.NEWS_READ()) RETURN
+		 NUMDIR1 = 0
+		 DO WHILE (BUFFER(SB:EB).NE.'.'.AND.NUMDIR1.LT.NUMDIR)
+		    NUMDIR1 = NUMDIR1 + 1
+		    CALL READ_QUEUE(%VAL(QXHDR),DUMMY,TEMP)
+		    DO WHILE (BUFFER(SB:EB).NE.'.'.AND.
+     &			.NOT.OTS$CVT_TI_L(BUFFER(SB:INDEX(
+     &			BUFFER(SB:EB),' ')+SB-2),J,,%VAL(1)))
+		       IF (.NOT.NEWS_READ()) RETURN
+		    END DO
+		    SB1 = INDEX(BUFFER(SB:EB),' ')+SB-1
+		    SB1 = FIRST_ALPHA(BUFFER(SB1:EB))+SB1-1
+		    TEMP(I*256+1:) = BUFFER(SB1:EB)
+		    CALL WRITE_QUEUE(%VAL(QXHDR),QXHDR,TEMP)
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+	      END IF
+	   END DO
+	   QXHDR = QXHDR1
+	   IER = 0
+	ELSE IF (REMOTE_SET.EQ.3.AND..NOT.XHDR) THEN
+	   STAT = .TRUE.
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).NE.'22') THEN
+	      IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (.NOT.OTS$CVT_TI_L(BUFFER(SB+4:
+     &		  INDEX(BUFFER(SB+4:),' ')+SB+2),I,,%VAL(1))) RETURN
+	      IF (BUFFER(:2).NE.'22'.OR.I.LT.START) THEN
+		 BUFFER(:3) = '500'
+		 DO WHILE (START.LE.F_NBULL.AND.BUFFER(:2).NE.'22')
+		    START = START + 1
+		    IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+		 IF (BUFFER(:2).NE.'22') THEN
+		    IER = 0
+		    END = START - 1
+		    RETURN
+		 END IF
+	      END IF
+	      IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+	      END = START + NUMDIR - 1
+	   END IF
+	   IER = 0
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   I = START
+	   DO WHILE (IER.EQ.0.AND.I.LE.END)
+	      IF (REMOTE_SET.EQ.1) THEN
+		 READ(REMOTE_UNIT,'(A)',IOSTAT=IER) BULLDIR_ENTRY
+	      ELSE IF (XHDR) THEN
+		 CALL READ_QUEUE(%VAL(QXHDR),QXHDR,TEMP)
+		 LTEMP = INDEX(TEMP,' ')
+		 CALL OTS$CVT_TI_L(TEMP(:LTEMP-1),MSG_NUM,,%VAL(1))
+		 CALL NEWS_TIME(TEMP(LTEMP+1:TRIM(TEMP(:256))),MSG_BTIM)
+		 DO J=257,512
+		    IF (TEMP(J:J).LT.' '.OR.ICHAR(TEMP(J:J)).GT.126)
+     &			TEMP(J:J) = ' '
+		 END DO
+		 DESCRIP = TEMP(257:512)
+		 CALL GET_FROM(FROM,TEMP(512:768),TRIM(TEMP(512:768)))
+	      ELSE
+		 IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			INDEX(BUFFER(SB+4:),' ')+SB+2),MSG_NUM,,%VAL(1))
+		 CALL NEWS_HEADER(IER)
+		 IF (IER.NE.0) RETURN
+	      END IF
+	      CALL WRITE_QUEUE(%VAL(ALL_DIR),ALL_DIR,BULLDIR_ENTRY)
+	      I = I + 1
+	      IF (REMOTE_SET.EQ.3.AND..NOT.XHDR.AND.I.LE.END) THEN
+		 IER = 2
+		 IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IF (BUFFER(:3).NE.'223') THEN
+		    END = I - 1
+		    IER = 0
+		    RETURN
+		 END IF
+		 IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IER = 0
+	      END IF
+	   END DO
+	END IF
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   IER = 1
+	   IF (STAT) THEN
+	      IF (.NOT.OTS$CVT_L_TI(BULL_POINT,NUMBER,,,)) RETURN
+	      IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	   END IF
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_LOGIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_CONNECTED/ NEWS_CONNECTED
+	LOGICAL NEWS_CONNECTED /.FALSE./
+
+	COMMON /XHDR/ XHDR
+	LOGICAL XHDR /.FALSE./
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+
+	IF (.NOT.NEWS_CONNECTED) THEN
+	   NEWS_LOGIN = .FALSE.
+	   CALL START_NEWS_TIMER()
+	   NEWS_CONNECTED = NEWS_CONNECT()
+	   CALL CANCEL_NEWS_TIMER()
+	   IF (.NOT.NEWS_CONNECTED) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (INDEX(BUFFER(SB:EB),'InterNetNews').GT.0) THEN
+	      IF (.NOT.NEWS_WRITE('mode reader')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	   END IF
+	   IF (.NOT.NEWS_WRITE('XHDR')) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   XHDR = BUFFER(:3).NE.'500'
+	   HEADER_SEEN = .FALSE.
+	   LF_SEEN = .FALSE.
+	   LAST_LF_SEEN = .FALSE.
+	   REAL_LF_SEEN = .FALSE.
+	   LAST_REAL_LF_SEEN = .FALSE.
+	END IF
+
+	NEWS_LOGIN = .TRUE.
+
+	RETURN
+	END
+
+
+	SUBROUTINE CONVERT_TO_GMT(BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MONTHS/ MONTH
+	CHARACTER*36 MONTH
+	DATA MONTH/'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'/
+
+	DIMENSION GMT_DIFF(2),BTIM(2)
+
+	CHARACTER HOUR*8
+	DATA HOUR /' '/
+
+	PARAMETER NZONES = 5
+
+	COMMON /ZONE/ ZONE,LZONE
+	CHARACTER*4 ZONE
+
+	CHARACTER ZONES*(NZONES*4)
+	DATA ZONES /'EST CST MST PST IST'/
+
+	CHARACTER*8 TIMES(1)
+	DATA TIMES /'-5:30'/
+
+	CHARACTER TIME*12
+
+	TO_GMT = .TRUE.
+
+	ENTRY CONVERT_FROM_GMT(BTIM)
+
+	IF (HOUR.EQ.' ') THEN
+	   IF (.NOT.SYS_TRNLNM_SYSTEM('LISP$TIME_ZONE',HOUR)) THEN
+	      IF (SYS_TRNLNM_SYSTEM('MULTINET_TIMEZONE',ZONE)
+     &	       .OR.SYS_TRNLNM_SYSTEM('PMDF_TIMEZONE',ZONE)) THEN
+		 IF (INDEX(ZONES,ZONE)/4.LT.4) THEN
+		    HOUR = CHAR(ICHAR('4')+(INDEX(ZONES,ZONE)+3)/4)//':00'
+		 ELSE
+		    HOUR = TIMES((INDEX(ZONES,ZONE)+3)/4-4)
+		 END IF
+	      ELSE
+		 HOUR = '00:00'
+	      END IF
+	   ELSE
+	      HOUR = HOUR(:TRIM(HOUR))//':00'
+	   END IF
+	   ZONE = 'GMT'
+	   IER = OTS$CVT_TI_L(HOUR(:INDEX(HOUR,':')-1),DIFF,,%VAL(1))
+	   IF (DIFF.GE.5.AND.DIFF.LE.8) THEN
+C
+C  Following computes DST based on US formula
+C
+	      IER = SYS$ASCTIM(,TIME,BTIM,)
+	      IER = OTS$CVT_TI_L(TIME(:2),DATE,,%VAL(1))
+	      CALL LIB$DAY_OF_WEEK(BTIM,DAY)
+	      M = (INDEX(MONTH,TIME(4:6))+2)/3
+	      IF (M.GE.4.AND.M.LE.10.AND.(M.NE.4.OR.DAY.LT.DATE)
+     &			.AND.(M.NE.10.OR.DATE-DAY.LT.24)) THEN
+		 DIFF = DIFF - 1
+		 IER = OTS$CVT_L_TI(DIFF,HOUR(:1),,,)
+	      END IF
+	   END IF
+	   IF (DIFF.LT.0) THEN
+	      PAST = .TRUE.
+	      HOUR = HOUR(2:)
+	   ELSE IF (DIFF.GT.12) THEN
+	      PAST = .TRUE.
+	      DIFF = 24 - DIFF
+	      HOUR(3:) = HOUR(INDEX(HOUR,':'):)
+	      IER = OTS$CVT_L_TI(DIFF,HOUR(:2),,,)
+	      IF (HOUR(:1).EQ.' ') HOUR = HOUR(2:)
+	   ELSE
+	      PAST = .FALSE.
+	   END IF
+	   LZONE = TRIM(ZONE)
+	   IER = SYS_BINTIM('0 '//HOUR(:TRIM(HOUR)),GMT_DIFF)
+	END IF
+
+	IF ((PAST.AND..NOT.TO_GMT).OR.(.NOT.PAST.AND.TO_GMT)) THEN
+	   IER = LIB$SUBX(BTIM,GMT_DIFF,BTIM)
+	ELSE
+	   IER = LIB$ADDX(BTIM,GMT_DIFF,BTIM)
+	END IF
+
+	TO_GMT = .FALSE.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE START_NEWS_TIMER()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER TIMADR(2)                       ! Buffer containing time
+						  ! in desired system format.
+	CHARACTER TIMBUF*16,SEC*4
+	DATA TIMBUF/'0 00:00:00.00'/
+
+	EXTERNAL KILL_NEWS_CONNECT
+
+	IF (TIMBUF(9:10).EQ.'00') THEN
+	   CALL LIB$GET_EF(WAITEFN)
+	   TIMBUF(9:10) = '30'
+	   IF (SYS_TRNLNM('BULL_NEWS_TIMER',SEC)) THEN
+	      IER = OTS$CVT_TI_L(SEC(:TRIM(SEC)),I,,%VAL(1))
+	      IF (IER.AND.I.GT.0) THEN
+		 IF (TRIM(SEC).EQ.1) THEN
+		    TIMBUF(9:10) = '0'//SEC(:1)
+		 ELSE
+		    TIMBUF(9:10) = SEC
+		 END IF
+	      END IF
+	   END IF
+	   IER = SYS$BINTIM(TIMBUF(:13),TIMADR)
+	END IF
+
+	IER = SYS$SETIMR(%VAL(WAITEFN),TIMADR,KILL_NEWS_CONNECT,)
+
+	RETURN
+
+	ENTRY CANCEL_NEWS_TIMER()
+
+	IER = SYS$CANCEL(%VAL(WAITEFN))
+
+	RETURN
+	END
+
+
+	SUBROUTINE KILL_NEWS_CONNECT()
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_CONNECTED/ NEWS_CONNECTED
+
+	IF (NEWS_CONNECTED) RETURN
+
+	NLUN = NEWS_GET_CHAN()
+
+	IER = SYS$CANCEL(%VAL(NLUN))
+
+	CALL NEWS_DISCONNECT()
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_HEADER(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /FOLLOWUP/ FOLLOWUP
+	CHARACTER*128 FOLLOWUP
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	COMMON /SENDER/ SENDER_LINE
+	CHARACTER*256 SENDER_LINE
+
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+
+	COMMON /NEWS2BULL/ NEWS2BULL
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	EX_BTIM(1) = 0
+	EX_BTIM(2) = 0
+
+	DESCRIP = ' '
+	FROM = ' '
+	SUBJECT_LINE = ' '
+	FROM_LINE = ' '
+	SENDER_LINE = ' '
+	NEWSGROUPS = ' '
+	FOLLOWUP = ' '
+	LREF = 0
+	NEWS2BULL = .FALSE.
+
+	MSGNUM = BUFFER(5:INDEX(BUFFER(5:),' ')-1+4)
+	LAST_FROM = .FALSE.
+
+	DO WHILE (BUFFER(SB:EB).NE.'.'.OR..NOT.LAST_REAL_LF_SEEN)
+	   IER = NEWS_READ()
+	   IF (.NOT.IER) RETURN
+	   IF (BUFFER(SB:EB).NE.'.') THEN
+	      IF (BUFFER(SB:SB+7).EQ.'Subject:'.AND.EB.GE.SB+9) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+9:EB))+SB+8
+		 DO I=SB1,EB
+		    IF (BUFFER(I:I).LT.' '.OR.ICHAR(BUFFER(I:I)).GT.126)
+     &			BUFFER(I:I) = ' '
+		 END DO
+		 SUBJECT_LINE = 'Subj: '//BUFFER(SB1:EB)
+		 DESCRIP = BUFFER(SB1:EB)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+4).EQ.'Date:'.AND.EB.GE.SB+6) THEN
+		 CALL NEWS_TIME(BUFFER(SB+6:EB),MSG_BTIM)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+7).EQ.'Expires:'.AND.EB.GE.SB+9) THEN
+		 CALL NEWS_TIME(BUFFER(SB+9:EB),EX_BTIM)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+4).EQ.'From:'.AND.EB.GE.SB+6) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+6:EB))+SB+5
+		 FROM_LINE = 'From: '//BUFFER(SB1:EB)
+		 CALL GET_FROM(FROM,BUFFER(SB1:EB),EB-SB1+1)
+		 LAST_FROM = .TRUE.
+	      ELSE IF (BUFFER(SB:SB+6).EQ.'Sender:'.AND.EB.GE.SB+8) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+8:EB))+SB+7
+		 SENDER_LINE = ': '//BUFFER(SB1:EB)
+		 LAST_FROM = .TRUE.
+	      ELSE IF (BUFFER(SB:SB+10).EQ.'Message-ID:'.AND.
+     &						    EB.GT.SB+11) THEN
+		 NEWS_MSGID = BUFFER(SB+13:EB-1)
+		 IF (LREF.EQ.0) THEN
+		    REFERENCES = BUFFER(SB+12:EB)
+		 ELSE
+		    REFERENCES = REFERENCES(:LREF)//' '//
+     &				BUFFER(SB+12:EB)
+		 END IF
+		 LREF = TRIM(REFERENCES)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+10).EQ.'Newsgroups:'.AND.
+     &						    EB.GT.SB+11) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+12:EB))+SB+11
+		 NEWSGROUPS = BUFFER(SB1:EB)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+11).EQ.'Followup-To:'.AND.
+     &						    EB.GT.SB+12) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+13:EB))+SB+12
+		 FOLLOWUP = BUFFER(SB1:EB)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+10).EQ.'References:'.AND.
+     &						    EB.GT.SB+11) THEN
+		 IF (LREF.EQ.0) THEN
+		    REFERENCES = BUFFER(SB+12:EB)
+		 ELSE
+		    REFERENCES = BUFFER(SB+12:EB)//' '//
+     &				REFERENCES(:LREF)
+		 END IF
+		 LREF = TRIM(REFERENCES)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (INDEX(BUFFER(SB:),
+     &		       'X-Newsreader: News2bull').EQ.1) THEN 
+	         NEWS2BULL = .TRUE.
+	         IF (LPATH.EQ.0) CALL GET_PATHNAME
+		 I = INDEX(BUFFER(SB:),'@')
+		 IF (I.GT.0) THEN
+	            SAMEHOST = STREQ(PATHNAME(2:LPATH),BUFFER(SB+I:EB))
+		 END IF
+	      ELSE IF (LAST_FROM.AND.BUFFER(SB:SB).EQ.' ') THEN
+		 IF (SENDER_LINE(:1).EQ.':') THEN 
+		    SENDER_LINE = SENDER_LINE(:TRIM(SENDER_LINE))//' '//
+     &				BUFFER(SB+FIRST_ALPHA(BUFFER(SB:EB))-1:EB)
+		 ELSE
+		    FROM_LINE = FROM_LINE(:TRIM(FROM_LINE))//' '//
+     &				BUFFER(SB+FIRST_ALPHA(BUFFER(SB:EB))-1:EB)
+		    CALL GET_FROM(FROM,FROM_LINE(7:),TRIM(FROM_LINE))
+		 END IF
+		 LAST_FROM = .TRUE.
+	      ELSE
+		 LAST_FROM = .FALSE.
+	      END IF
+	      IF (.NOT.LAST_FROM.AND.SENDER_LINE(:1).EQ.':') THEN
+		 SENDER_LINE = 'From'//SENDER_LINE
+	      END IF
+	   END IF
+	END DO
+
+	NEWS2BULL = NEWS2BULL.AND.SAMEHOST
+
+	IER = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION FIRST_ALPHA(INPUT)
+
+	CHARACTER*(*) INPUT
+
+	DO I=1,LEN(INPUT)
+	   IF (ICHAR(INPUT(I:I)).LT.32) INPUT(I:I) = ' '
+	END DO
+
+	DO FIRST_ALPHA=1,LEN(INPUT)
+	   IF (ICHAR(INPUT(FIRST_ALPHA:FIRST_ALPHA)).GT.32) RETURN
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE REMOTE_READ_MESSAGE(BULL_SEARCH,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	CHARACTER*8 NUMBER
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 5,BULL_SEARCH
+	ELSE
+	   IER = 2
+	   IF (BULL_SEARCH.LT.F_START) BULL_SEARCH = F_START
+	   IF (.NOT.OTS$CVT_L_TI(BULL_SEARCH,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('ARTICLE '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).NE.'22') RETURN
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_GET_NEWEST_MSG(IN_BTIM,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	DIMENSION IN_BTIM(2)
+
+	CHARACTER TIME*20,FIRST*80
+
+	CHARACTER*8 NUMBER
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(3A)',IOSTAT=IER) 12,IN_BTIM(1),IN_BTIM(2)
+	   IF (IER.EQ.0) THEN
+	      READ (REMOTE_UNIT,'(A)',IOSTAT=IER) START
+	   END IF
+	ELSE IF (READIT.EQ.1) THEN
+	   I = NEWS_FIND_SUBSCRIBE()
+	   START = (LAST_NEWS_READ2(2,I).AND.'1FFF'X) +
+     &			LAST_NEWS_READ(2,I) + 1
+	   IF (START.GT.F_NBULL) THEN
+	      START = -1
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = MIN(8191,F_NBULL-LAST_NEWS_READ(2,I))
+     &			.OR.(LAST_NEWS_READ2(2,I).AND.'E000'X)
+	   END IF
+	ELSE
+	   START = -1
+	   CALL NEWNEWS(IN_BTIM,IER)
+	   IF (IER.NE.0) START = IER
+C
+C   The following code makes use of the NNTP command NEWNEWS, but is
+C   known to be slow and buggy in many servers.
+C
+C          IER = SYS$ASCTIM(,TIME,IN_BTIM,)
+C          CALL DATE_TIME(TIME)
+C          SKIP = 0
+C          DO WHILE (SKIP.GE.0)
+C             IF (.NOT.NEWS_WRITE('NEWNEWS '//FOLDER_NAME(:TRIM(
+C     &           FOLDER_NAME))//' '//TIME)) RETURN
+C             IF (.NOT.NEWS_READ()) RETURN
+C             IF (BUFFER(:2).EQ.'23') THEN
+C                IF (.NOT.NEWS_READ()) CALL EXIT
+C                DO I=1,SKIP
+C                   IF (.NOT.NEWS_READ()) CALL EXIT
+C                END DO
+C                IF (FIRST.EQ.'.') RETURN
+C                DO WHILE (BUFFER(SB:EB).NE.'.')
+C                   IF (.NOT.NEWS_READ()) CALL EXIT
+C                END DO
+C                IF (.NOT.NEWS_WRITE('STAT '//FIRST(:TRIM(FIRST))))
+C     &                                   CALL EXIT
+C                IF (.NOT.NEWS_READ()) CALL EXIT
+C                IF (BUFFER(:2).EQ.'22') THEN
+C                   IF (BUFFER(5:INDEX(BUFFER(5:),' ')+3).EQ.'0') THEN
+C                      I = F_NBULL + 1
+C                      DO WHILE (I.GE.F_START.AND.(FIRST(:TRIM(FIRST)).NE.
+C     &                    BUFFER(INDEX(BUFFER,'<'):INDEX(BUFFER,'>'))
+C     &                    .OR.I.GT.F_NBULL))
+C                         I = I - 1
+C                         IF (.NOT.OTS$CVT_L_TI(I,NUMBER,,,)) RETURN
+C                         IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+C                         IF (.NOT.NEWS_READ()) RETURN
+C                      END DO
+C                      IF (I.GE.F_START) START = I
+C                   ELSE
+C                      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+C     &                   INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+C                   END IF
+C                   RETURN
+C                END IF
+C             END IF
+C             SKIP = SKIP + 1
+C          END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_COPY_BULL(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(A)',IOSTAT=IER1) 2
+	   IER = IER1
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_WRITE_BULL_FILE(OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) OUTPUT
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 6,OUTPUT
+	ELSE
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_REMOTE_MESSAGE(IER)
+C
+C  SUBROUTINE GET_REMOTE_MESSAGE
+C
+C  FUNCTION:
+C       Gets remote message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REMOTE_READ_MESSAGE/ SCRATCH_R1
+	DATA SCRATCH_R1 /0/
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	COMMON /LOCAL_UPDATE/ LOCAL_UPDATE1
+
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+
+	CHARACTER*256 TEMP
+
+	IF (SCRATCH_R1.NE.0) THEN               ! Is queue empty?
+	   SCRATCH_R = SCRATCH_R1               ! No, set queue pointer to head
+	ELSE                                    ! Else if queue is empty
+	   CALL INIT_QUEUE(SCRATCH_R,INPUT)
+	   SCRATCH_R1 = SCRATCH_R               ! Init header pointer
+	END IF
+
+	ILEN = 128
+	IER = 0
+	LENGTH = 0
+	LTEMP = 0
+	HEADER_SEEN = .FALSE.
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   LSUB = TRIM(SUBJECT_LINE)
+	   LFRO = TRIM(FROM_LINE)
+	   IF (LOCAL_UPDATE1.NE.0) THEN
+	      ILEN = 1
+	      INPUT(:1) = CHAR(0)
+	   END IF
+	END IF
+
+	DO WHILE (ILEN.GT.0.AND.IER.EQ.0)
+	   IF (REMOTE_SET.EQ.1) THEN
+	      READ (REMOTE_UNIT,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	   ELSE
+	      IF (ILEN.EQ.128) ILEN = 0
+	      IF (LTEMP.GT.0) THEN
+		 ILEN = MIN(128,LTEMP)
+		 INPUT = TEMP(:ILEN)
+		 LTEMP = LTEMP - ILEN
+	      END IF
+	      IF (ILEN.LT.128) THEN
+		 IF (LFRO.GT.0) THEN
+		    IF (LOCAL_UPDATE1.NE.0) THEN
+		       CALL COMPRESS(FROM_LINE(:LFRO),FROM_LINE,LFRO)
+		    END IF
+		    LTEMP = LFRO
+		    LFRO = 0
+		    IER = 0
+		    TEMP = CHAR(LTEMP)//FROM_LINE
+		    LTEMP = LTEMP + 1
+		    LINP = MIN(LTEMP,128-ILEN)
+		    INPUT = INPUT(:ILEN)//TEMP(:LINP)
+		    ILEN = ILEN + LINP
+		    LTEMP = LTEMP - LINP
+		    TEMP = TEMP(LINP+1:)
+		 ELSE IF (LSUB.GT.0) THEN
+		    IF (LOCAL_UPDATE1.NE.0) THEN
+		       CALL COMPRESS(SUBJECT_LINE(:LSUB),SUBJECT_LINE,LSUB)
+		    END IF
+		    LTEMP = LSUB
+		    LSUB = 0
+		    IER = 0
+		    TEMP = CHAR(LTEMP)//SUBJECT_LINE
+		    LTEMP = LTEMP + 1
+		    LINP = MIN(LTEMP,128-ILEN)
+		    INPUT = INPUT(:ILEN)//TEMP(:LINP)
+		    ILEN = ILEN + LINP
+		    LTEMP = LTEMP - LINP
+		    TEMP = TEMP(LINP+1:)
+		 ELSE
+		    IER = NEWS_READ()
+		    IF (IER.AND.(BUFFER(SB:EB).NE.'.'
+     &			.OR..NOT.LAST_REAL_LF_SEEN)) THEN
+		       IER = 0
+		       LTEMP = EB-SB+1
+		       IF (LTEMP.GT.0) THEN
+			  TEMP = CHAR(LTEMP)//BUFFER(SB:SB+LTEMP-1)
+			  IF (.NOT.HEADER_SEEN) THEN
+			     IF (TRIM(TEMP).EQ.0) THEN
+				HEADER_SEEN = .TRUE.
+			     ELSE IF ((INDEX(TEMP,': ').EQ.0.AND.
+     &				   INDEX(TEMP,':'//CHAR(9)).EQ.0.AND.ICHAR(
+     &				   TEMP(2:2)).GT.32.AND.LTEMP.LT.255).OR.
+     &				   (LTEMP.EQ.254.AND..NOT.LAST_LF_SEEN)) THEN
+				TEMP = CHAR(LTEMP+1)
+     &					   //' '//BUFFER(SB:SB+LTEMP-1)
+				LTEMP = LTEMP + 1
+			     END IF
+			  ELSE IF (BUFFER(SB:SB).EQ.'.') THEN
+			     TEMP = CHAR(LTEMP-1)//BUFFER(SB+1:SB+LTEMP-1)
+			     LTEMP = LTEMP - 1
+			  END IF
+			  IF (LOCAL_UPDATE1.NE.0) THEN
+			     CALL COMPRESS(TEMP(2:LTEMP+1),TEMP(2:),LTEMP)
+			     TEMP(:1) = CHAR(LTEMP)
+			  END IF
+		       ELSE
+			  HEADER_SEEN = .TRUE.
+			  TEMP = CHAR(1)//' '
+			  LTEMP = 1
+		       END IF
+		       LTEMP = LTEMP + 1
+		       LINP = MIN(LTEMP,128-ILEN)
+		       INPUT = INPUT(:ILEN)//TEMP(:LINP)
+		       ILEN = ILEN + LINP
+		       LTEMP = LTEMP - LINP
+		       TEMP = TEMP(LINP+1:)
+		    ELSE IF (IER) THEN
+		       IER = 0
+		       INPUT = INPUT(:ILEN)//CHAR(0)
+		       ILEN = -128
+		    ELSE
+		       ILEN = 128
+		    END IF
+		 END IF
+	      ELSE
+		 TEMP = TEMP(129:)
+	      END IF
+	   END IF
+	   IF (IER.NE.0.AND.ILEN.GT.0) THEN
+	      CALL ERRSNS(IDUMMY,IER1)
+	      IF (IER1.EQ.RMS$_RER) THEN        ! Ignore this error
+		 IER = 0
+		 ILEN = 0
+	      ELSE
+		 CALL SYS_GETMSG(IER1)
+		 LENGTH = 0
+		 IER1 = IER
+		 CALL DISCONNECT_REMOTE
+		 IER = IER1     ! IER is set to 0 by DISCONNECT_REMOTE
+	      END IF
+	   ELSE IF (ABS(ILEN).EQ.128) THEN
+	      CALL WRITE_QUEUE(%VAL(SCRATCH_R),SCRATCH_R,INPUT)
+	      LENGTH = LENGTH + 1
+	   END IF
+	END DO
+
+	HEADER_SEEN = .TRUE.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE REMOTE_REMOVE_FOLDER(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+C
+C  SUBROUTINE CONNECT_REMOTE_FOLDER
+C
+C  FUNCTION: Connects to folder that is located on other DECNET node.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	DATA REMOTE_UNIT /15/
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /READIT/ READIT
+
+	COMMON /NEWS_INIT/ END_READ
+
+	COMMON /ALT_FOUND/ ALT_FOUND
+	CHARACTER*128 ALT_FOUND
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*12 FOLDER_BBOARD_SAVE,FOLDER_OWNER_SAVE
+	CHARACTER*44 FOLDER_SAVE
+	CHARACTER*64 ALT_SAVE
+
+	DIMENSION DUMMY(4)
+
+	IF (FOLDER1(:1).GE.'a'.AND.FOLDER1(:1).LE.'z') THEN
+	   ALT_SET_SAVE = ALT_SET()
+	   IF (ALT_SET_SAVE) CALL UNSET_ALT
+	   END_READ = 0
+	   IER = 0
+	   IF (.NOT.NEWS_LOGIN()) THEN
+	      IER = 2
+	      IF (.NOT.TEST_ALT(FOLDER1)) RETURN
+	      IER = 1
+	   END IF
+	   IF (IER.NE.1) CALL NEWS_GROUP(IER)
+	   IF (IER.EQ.1) THEN
+	      IF (TEST_ALT(FOLDER1)) THEN
+		 IER1 = SET_ALT(ALT_FOUND)
+		 IF (IER1) CALL NEWS_GROUP(IER)
+		 IF (.NOT.IER1.OR.IER.NE.0) THEN
+		    CALL UNSET_ALT
+	   	    IF (ALT_SET_SAVE) CALL SET_ALT(ALT_SAVE)
+		    RETURN
+		 END IF
+		 ALT_SAVE = FOLDER1(INDEX(':',FOLDER1)+1:)
+	         IER = 0
+	      ELSE IF (ALT_SET_SAVE) THEN
+	         CALL SET_ALT(ALT_SAVE)
+		 IER = 1
+	      END IF
+	      RETURN
+	   END IF
+	   IF (REMOTE_SET.EQ.1) CLOSE(UNIT=REMOTE_UNIT)
+	   RETURN
+	END IF
+
+	REMOTE_UNIT = 31 - REMOTE_UNIT
+
+	SAME = .TRUE.
+	LEN_BBOARD = TRIM(FOLDER1_BBOARD)
+	IF (INDEX(FOLDER1_BBOARD,'*').GT.0) THEN  ! Remote folder name different
+	   SAME = .FALSE.                         ! from local?  Yes.
+	   LEN_BBOARD = LEN_BBOARD - 1
+	END IF
+
+	OPEN (UNIT=REMOTE_UNIT,STATUS='UNKNOWN',IOSTAT=IER,RECL=256,
+     &		FILE=FOLDER1_BBOARD(3:LEN_BBOARD)//'::"TASK=BULLETIN1"')
+
+	IF (IER.EQ.0) THEN
+	   IF (.NOT.SAME) THEN
+	      FOLDER1_FILE = FOLDER_FILE
+	      FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//FOLDER1
+	      REMOTE_SET_SAVE = REMOTE_SET
+	      REMOTE_SET = .FALSE.
+	      CALL OPEN_BULLDIR
+	      CALL READDIR(0,IER)
+	      CALL CLOSE_BULLDIR
+	      REMOTE_SET = REMOTE_SET_SAVE
+	      FOLDER_FILE = FOLDER1_FILE
+	      FOLDER_SAVE = FOLDER1
+	      FOLDER1 = BULLDIR_HEADER(13:)
+	      IF (NEMPTY.EQ.0) FOLDER1 = FOLDER1(:25)
+	   END IF
+	   SYSLOG = .FALSE.
+	   IF (READIT.EQ.1) THEN
+	      WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 1,'SYSTEM?'
+	      READ(REMOTE_UNIT,'(A)',IOSTAT=IER) IER1
+	      IF (IER1) THEN
+		 WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 1,FOLDER1//'+'
+		 SYSLOG = .TRUE.
+	      END IF
+	   END IF
+	   IF (.NOT.SYSLOG) THEN
+	      WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 1,FOLDER1
+	   END IF
+	   FOLDER_OWNER_SAVE = FOLDER1_OWNER
+	   FOLDER_BBOARD_SAVE = FOLDER1_BBOARD
+	   FOLDER_NUMBER_SAVE = FOLDER1_NUMBER
+	   IF (IER.EQ.0) THEN
+	      IF (SYSLOG) THEN
+		 READ(REMOTE_UNIT,'(7A)',IOSTAT=IER)IER1,READ_ONLY,
+     &		   DUMMY(1),DUMMY(2),DUMMY(3),DUMMY(4),FOLDER1_COM
+	      ELSE
+		 READ(REMOTE_UNIT,'(5A)',IOSTAT=IER)IER1,READ_ONLY,
+     &		   DUMMY(1),DUMMY(2),FOLDER1_COM
+	      END IF
+	   END IF
+	   IF (.NOT.SAME) FOLDER1 = FOLDER_SAVE
+	   FOLDER1_BBOARD = FOLDER_BBOARD_SAVE
+	   FOLDER1_NUMBER =  FOLDER_NUMBER_SAVE
+	   FOLDER1_OWNER = FOLDER_OWNER_SAVE
+	END IF
+
+	IF (IER.NE.0.OR..NOT.IER1) THEN
+	   CLOSE (UNIT=REMOTE_UNIT)
+	   REMOTE_UNIT = 31 - REMOTE_UNIT
+	   IF (IER.EQ.0.AND.FOLDER_NUMBER_SAVE.GE.0.AND.
+     &	       TEST_BULLCP().NE.2) THEN                 ! Not BULLCP process
+	      IF (TEST2(BRIEF_FLAG,FOLDER_NUMBER_SAVE)
+     &		  .OR.TEST2(SET_FLAG,FOLDER_NUMBER_SAVE)) THEN
+		 CALL OPEN_BULLUSER_SHARED
+		 CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+		 CALL CLR2(BRIEF_FLAG,FOLDER_NUMBER_SAVE)
+		 CALL CLR2(SET_FLAG,FOLDER_NUMBER_SAVE)
+		 IF (IER.EQ.0) REWRITE (4) USER_ENTRY
+		 CALL CLOSE_BULLUSER
+	      END IF
+	   END IF
+	   IER = 2
+	ELSE
+	   CLOSE (UNIT=31-REMOTE_UNIT)
+C
+C  If remote folder has returned a last read time for the folder,
+C  and if in /LOGIN mode, or last selected folder was a different
+C  folder, or folder specified with "::", then update last read time.
+C
+	   IF (((FOLDER_NUMBER.NE.FOLDER1_NUMBER.OR.READIT.EQ.1)
+     &		.AND.(DUMMY(1).NE.0.OR.DUMMY(2).NE.0))
+     &		.OR.FOLDER1_NUMBER.EQ.-1) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER1_NUMBER+1),DUMMY)
+	      IF (SYSLOG) THEN
+		 CALL COPY2(LAST_SYS_BTIM(1,FOLDER1_NUMBER+1),DUMMY(3))
+	      END IF
+	   END IF
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_GET_HEADER(BULLETIN_NUM,ICOUNT,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /NEXT/ NEXT
+	LOGICAL NEXT /.FALSE./
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	CHARACTER*8 NUMBER
+
+	DIMENSION IN_BTIM(2)
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   IF (ICOUNT.GE.0) THEN
+	      WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 8,ICOUNT
+	   ELSE
+	      WRITE (REMOTE_UNIT,'(3A)',IOSTAT=IER) 8,-1,MSG_KEY
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (ICOUNT.EQ.0) THEN
+		 READ (REMOTE_UNIT,'(2A)',IOSTAT=IER) ICOUNT,BULLDIR_HEADER
+	      ELSE IF (ICOUNT.EQ.-1) THEN
+		 READ (REMOTE_UNIT,'(2A)',IOSTAT=IER1) IER,BULLDIR_ENTRY
+		 IF (IER1.GT.0) THEN
+		    CALL ERROR_AND_EXIT
+		 ELSE IF (IER.NE.0) THEN
+		    CALL CONVERT_ENTRY_FROMBIN
+		 END IF
+		 RETURN
+	      ELSE
+		 READ (REMOTE_UNIT,'(2A)',IOSTAT=IER) ICOUNT,BULLDIR_ENTRY
+	      END IF
+	   END IF
+	   IF (IER.GT.0) THEN
+	      CALL ERROR_AND_EXIT
+	   ELSE IF (ICOUNT.EQ.1) THEN
+	      CALL CONVERT_HEADER_FROMBIN
+	   ELSE
+	      CALL CONVERT_ENTRY_FROMBIN
+	   END IF
+	ELSE IF (REMOTE_SET.EQ.3) THEN
+	   IF (ICOUNT.EQ.0) THEN
+	      NBULL = F_NBULL
+	      ICOUNT = 1
+	      RETURN
+	   ELSE IF (ICOUNT.EQ.-1) THEN
+	      IER = 2
+	      CALL GET_MSGBTIM(MSG_KEY,IN_BTIM)
+	      CALL REMOTE_GET_NEWEST_MSG(IN_BTIM,START)
+	      IF (START.EQ.-1) RETURN
+	      IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+	      IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+	   ELSE
+	      IER = 2
+	      IF (NEXT.AND..NOT.NEWGROUP) THEN
+		 IF (.NOT.NEWS_WRITE('NEXT')) CALL ERROR_AND_EXIT
+		 IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		 IF (BUFFER(:3).NE.'223') RETURN
+		 IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+		 IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+	      ELSE
+		 IF (ICOUNT.LT.F_START) ICOUNT = F_START
+		 IF (ICOUNT.GT.F_NBULL) ICOUNT = F_NBULL
+		 IF (.NOT.OTS$CVT_L_TI(ICOUNT,NUMBER,,,)) RETURN
+		 IF (.NOT.NEWS_WRITE('HEAD '//NUMBER))
+     &						CALL ERROR_AND_EXIT
+		 IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+	      END IF
+	      IF (BUFFER(:2).NE.'22') THEN
+		 DO WHILE (NEXT.AND.NEWGROUP.AND.ICOUNT.GT.F_START)
+		    ICOUNT = ICOUNT - 1
+		    IF (.NOT.OTS$CVT_L_TI(ICOUNT,NUMBER,,,)) RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD '//NUMBER))
+     &						CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		    IF (BUFFER(:2).EQ.'22') THEN
+		       NEXT = .FALSE.
+		       DO WHILE (BUFFER(SB:EB).NE.'.')
+			  IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		       END DO
+		    END IF
+		 END DO
+		 IF (INCMD(:4).EQ.'BACK'.AND.ICOUNT.GE.F_START) THEN
+		    IF (.NOT.NEWS_WRITE('LAST')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		    IF (BUFFER(:3).NE.'223') RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		 ELSE IF (INCMD(:4).NE.'READ'.AND..NOT.NEXT) THEN
+		    IF (.NOT.NEWS_WRITE('NEXT')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		    IF (BUFFER(:3).NE.'223') RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		 END IF
+	      END IF
+	      IF (BUFFER(:2).NE.'22') RETURN
+	      IER = OTS$CVT_TI_L(BUFFER(5:INDEX(BUFFER(5:),' ')+3),
+     &							ICOUNT,,%VAL(1))
+	      IF (.NOT.IER) RETURN
+	      START = ICOUNT
+	      BULLETIN_NUM = START
+	   END IF
+	   NEWGROUP = .FALSE.
+	   MESSAGE_ID = BUFFER(INDEX(BUFFER,'<')+1:INDEX(BUFFER,'>')-1)
+	   IER = 0
+	   CALL NEWS_HEADER(IER)
+	   CALL CONVERT_FROM_GMT(MSG_BTIM)
+	   IF (IER.GT.0) THEN
+	      CALL ERROR_AND_EXIT
+	   ELSE
+	      CALL CONVERT_ENTRY_FROMBIN
+	   END IF
+	   BLOCK = START
+	   MSG_NUM = START
+	   SYSTEM = 0
+	   IF (ICOUNT.NE.-1) THEN
+	      ICOUNT = ICOUNT + 1
+	   ELSE
+	      IER = START
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_MSGBTIM(MSG_KEY,BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER BTIM(2)
+
+	CHARACTER*8 MSG_KEY,INPUT
+
+	INPUT = MSG_KEY
+
+	DO I=1,8
+	   INPUT(9-I:9-I) = MSG_KEY(I:I)
+	END DO
+
+	CALL LIB$MOVC3(8,%REF(INPUT),BTIM(1))
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_GROUP(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	IF (INDEX(FOLDER1_DESCRIP,' ').EQ.0) THEN
+	   IER = 1
+	   RETURN
+	END IF
+
+	IER = NEWS_WRITE('GROUP '//
+     &			 FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,' ')-1))
+	IF (.NOT.IER) RETURN
+
+	IER = NEWS_READ()
+	IF (.NOT.IER) RETURN
+
+	IER = 1
+
+	IF (BUFFER(:3).EQ.'411') RETURN
+
+	NEWGROUP = .TRUE.
+
+	BUFFER = BUFFER(5:)
+
+	IER = OTS$CVT_TI_L(BUFFER(:INDEX(BUFFER,' ')-1),F1_COUNT,,%VAL(1))
+	IF (.NOT.IER) RETURN
+	BUFFER = BUFFER(INDEX(BUFFER,' ')+1:)
+	IER = OTS$CVT_TI_L(BUFFER(:INDEX(BUFFER,' ')-1),F1_START,,%VAL(1))
+	IF (.NOT.IER) RETURN
+	BUFFER = BUFFER(INDEX(BUFFER,' ')+1:)
+	IER = OTS$CVT_TI_L(BUFFER(:INDEX(BUFFER,' ')-1),F1_NBULL,,%VAL(1))
+	IF (.NOT.IER) RETURN
+	BUFFER = BUFFER(INDEX(BUFFER,' ')+1:)
+
+	IER = NEWS_WRITE('STAT')
+	IF (.NOT.IER) RETURN
+
+	IER = NEWS_READ()
+	IF (.NOT.IER) RETURN
+
+	IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			   INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+	IF (IER.AND.START.GT.F1_START) F1_START = START
+
+	IF (F1_START.EQ.0) F1_NBULL = 0
+
+	IER = 0
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_TIME(INTIME,BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INTIME
+
+	CHARACTER*28 TIME
+
+	DIMENSION DIFF(2)
+
+	I = 1
+	LTIME = TRIM(INTIME)
+	DO WHILE (I.LE.LTIME.AND.(ICHAR(INTIME(I:I)).LT.ICHAR('0').OR.
+     &			   ICHAR(INTIME(I:I)).GT.ICHAR('9')))
+	   I = I + 1
+	END DO
+
+	IF (I.GT.LTIME) THEN
+	   CALL SYS_BINTIM('-',BTIM)
+	   RETURN
+	END IF
+
+	CALL STR$UPCASE(TIME,INTIME(I:))
+
+	DO J = 1,2
+	   I = 1
+	   DO WHILE (TIME(I:I).NE.' '.AND.I.LT.LEN(TIME))
+	      I = I + 1
+	   END DO
+	   TIME(I:I) = '-'
+	END DO
+
+	IF (I.EQ.LEN(TIME)) RETURN
+
+	IF (TIME(I+3:I+3).EQ.' ') THEN
+	   IF (TIME(I+1:I+1).EQ.'9'.OR.TIME(I+1:I+1).EQ.'8') THEN
+	      TIME = TIME(:I)//'19'//TIME(I+1:)
+	   ELSE
+	      TIME = TIME(:I)//'20'//TIME(I+1:)
+	   END IF
+	END IF
+
+	I = 1
+	DO J = 1,2
+	   DO WHILE (TIME(I:I).NE.' '.AND.I.LE.LEN(TIME))
+	      I = I + 1
+	   END DO
+	   I = I + 1
+	END DO
+
+	IF (I-2.GT.LEN(TIME).OR.I-2.LE.0) THEN
+	   CALL SYS_BINTIM('-',BTIM)
+	   RETURN
+	END IF
+
+	IF (INDEX(TIME(:I-2),'.').GT.0) THEN
+	   CALL SYS_BINTIM(TIME(:INDEX(TIME(:I-2),'.'))//'00',BTIM)
+	ELSE IF (TIME(I-4:I-4).EQ.':'.AND.TIME(I-7:I-7).EQ.':') THEN
+	   CALL SYS_BINTIM(TIME(:I-2)//'.00',BTIM)
+	ELSE
+	   CALL SYS_BINTIM(TIME(:I-2)//':00.00',BTIM)
+	END IF
+
+	IF (TIME(I:I).EQ.'+'.OR.TIME(I:I).EQ.'-') THEN
+	   IER = SYS_BINTIM('0 '//TIME(I+1:I+2)//':'//TIME(I+3:I+4),DIFF)
+	   IF (IER) THEN
+	      IF (TIME(I:I).EQ.'-') THEN
+		 IER = LIB$SUBX(BTIM,DIFF,BTIM)
+	      ELSE
+		 IER = LIB$ADDX(BTIM,DIFF,BTIM)
+	      END IF
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_LIST
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /LOCAL_UPDATE/ LOCAL_UPDATE1
+	DATA LOCAL_UPDATE1/0/
+
+	COMMON /NEWSLIST/ NEWSLIST
+
+	CHARACTER TODAY*24
+
+	DIMENSION EXPIRED(2)
+
+	CALL LIB$DATE_TIME(TODAY)
+
+	IF (.NOT.NEWS_LOGIN()) RETURN
+
+	IF (.NOT.NEWS_WRITE('LIST')) RETURN
+	IF (.NOT.NEWS_READ()) RETURN
+	IF (BUFFER(:3).NE.'215') RETURN
+
+	SPECIAL = SYS_TRNLNM('BULL_SPECIAL_NEWS_UPDATE','DEFINED').OR.
+     &	 (INDEX(TODAY,' 03:').NE.0)     ! Delete non-existant groups at 3
+
+	CALL INIT_QUEUE(LOCAL_UPDATE1,%DESCR(NEWS_FOLDER_NUMBER))
+
+	LOCAL_UPDATE = LOCAL_UPDATE1
+
+	NEWSLIST = .TRUE.
+	CALL OPEN_BULLNEWS_SHARED       ! Open folder file
+
+	NEWS_FOLDER1_BBOARD = '::'
+
+	CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER1)
+	IF (IER1.NE.0) THEN
+	   NEWS_FOLDER1 = 'a'
+	   NEWS_FOLDER1_NUMBER = 1000
+	   NEWS_F1_COUNT = 1001
+	   NEWS_F1_EXPIRE = 14
+	   NEWS_F1_EXPIRE_LIMIT = 0
+	   NEWS_F1_FLAG = 0
+	   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',EXPIRED)
+	   CALL GET_MSGKEY(EXPIRED,NEWS_F1_EXPIRED_DATE)
+	   WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	END IF
+	NEWS_FLAG_DEFAULT = NEWS_F1_FLAG
+	NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+	NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	IF (NEWS_F1_COUNT.LT.1001) NEWS_F1_COUNT = 1001
+	NEWS_F_COUNT = NEWS_F1_COUNT
+	DAMAGED = .FALSE.
+	DO WHILE (NEWS_READ().AND.BUFFER(SB:EB).NE.'.')
+	   FLEN = INDEX(BUFFER(SB:),' ') - 1
+	   IF (INDEX(BUFFER(SB:),' ').EQ.0) DAMAGED = .TRUE.
+	   NEWS_FOLDER1 = BUFFER(SB:MIN(44,FLEN)+SB-1)
+	   IF (IER1.EQ.0) THEN
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(NEWS_FOLDER1,IER)
+	   END IF
+	   SP = FLEN+SB+1
+	   EP = INDEX(BUFFER(SP:),' ')+SP-2
+	   IF (INDEX(BUFFER(SP:),' ').EQ.0) DAMAGED = .TRUE.
+	   IER2 = OTS$CVT_TI_L(BUFFER(SP:EP),NEWS_F1_NBULL,,%VAL(1))
+	   SP = EP + 2
+	   EP = INDEX(BUFFER(SP:),' ')+SP-2
+	   IF (INDEX(BUFFER(SP:),' ').EQ.0) DAMAGED = .TRUE.
+	   IER2 = OTS$CVT_TI_L(BUFFER(SP:EP),NEWS_F1_START,,%VAL(1))
+	   IF (NEWS_F1_START.EQ.0) NEWS_F1_NBULL = 0
+	   CALL SYS_BINTIM('-',NEWS_F1_NEWEST_BTIM)
+	   SP = EP + 1
+	   IF (IER.EQ.0.AND.IER1.EQ.0)
+     &	      NEWS_F1_FLAG = IBCLR(NEWS_F1_FLAG,10)  ! Old bug caused this.
+	   IF (IER.NE.0.OR.IER1.NE.0) THEN
+	      IF ((FLEN.LE.44.OR.FLEN-44+EB-SP+1.LT.
+     &	          LEN(NEWS_FOLDER1_DESCRIP)).AND.DAMAGED) THEN
+	         IF (FLEN.GT.44) THEN
+		    NEWS_FOLDER1_DESCRIP = BUFFER(SB+44:FLEN+SB-1)//
+     &					   BUFFER(SP:EB)
+	         ELSE
+		    NEWS_FOLDER1_DESCRIP = BUFFER(SP:EB)
+	         END IF
+		 CALL ADD_NEW_NEWS_ENTRY(FLEN,LOCAL_UPDATE)
+	      END IF
+           ELSE
+	      CALL UPDATE_NEWS_ENTRY(SPECIAL,LOCAL_UPDATE,FLEN,SP)
+	   END IF
+	   IF (DAMAGED) THEN
+	      IER = NEWS_READ()
+	      DAMAGED = .FALSE.
+	   END IF
+	END DO
+
+	CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER1)
+	NEWS_F1_COUNT = NEWS_F_COUNT
+	REWRITE (7) NEWS_FOLDER1_COM
+
+	OPEN (UNIT=33,FILE=FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &        'BULL_ALT_NEWS.LIS',IOSTAT=IER,STATUS='OLD',READONLY)
+	
+	DO WHILE (IER.EQ.0)
+	   READ (33,'(A)',IOSTAT=IER) INPUT
+	   IF (IER.EQ.0) THEN 
+	      FLEN = INDEX(INPUT,':')-1
+	      NEWS_FOLDER1 = INPUT(:FLEN)
+	      IF (SET_ALT(INPUT(FLEN+2:))) THEN
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP(NEWS_FOLDER1,IER1)
+		 IF (IER1.NE.0) THEN
+		    FOLDER1_DESCRIP = NEWS_FOLDER1
+	            IF (FLEN.GT.44) THEN
+	   	       NEWS_FOLDER1_DESCRIP = INPUT(45:FLEN)
+	            ELSE
+	               NEWS_FOLDER1_DESCRIP = ' '
+	   	    END IF
+	         END IF
+		 CALL NEWS_GROUP(IER)
+		 IF (IER.EQ.0) THEN 
+	            NEWS_F1_NBULL = F1_NBULL
+	            NEWS_F1_START = F1_START
+		    IF (NEWS_F1_START.EQ.0) NEWS_F1_NBULL = 0
+		    IF (IER1.NE.0) THEN
+		       CALL ADD_NEW_NEWS_ENTRY(FLEN,LOCAL_UPDATE)
+		    ELSE
+	               CALL UPDATE_NEWS_ENTRY(.FALSE.,LOCAL_UPDATE,FLEN,0)
+		    END IF
+		 END IF
+	      END IF
+	   END IF
+	   IF (IER.NE.0) CLOSE (UNIT=33)
+	   IF (ALT_SET()) THEN
+	      CALL UNSET_ALT
+	      IF (.NOT.NEWS_LOGIN()) RETURN
+	   END IF
+	END DO
+
+	IF (SPECIAL) THEN
+	   CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+	   LAST = FOLDER1_NUMBER
+	   DO WHILE (IER.EQ.0)
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+	      DO WHILE (IER.EQ.0.AND.LAST.EQ.FOLDER1_NUMBER) ! oops
+		 DELETE (7)
+		 CALL READ_FOLDER_FILE_TEMP(IER)
+	      END DO
+	      LAST = FOLDER1_NUMBER
+	      IF (IER.EQ.0.AND..NOT.BTEST(NEWS_F1_FLAG,10)) THEN
+		 NEWS_F1_NBULL = F1_NBULL
+		 NEWS_F1_START = F1_START
+		 NEWS_F1_COUNT = F1_COUNT
+		 CALL NEWS_GROUP(IER)
+		 IF (IER.EQ.1.AND.TEST_ALT(NEWS_FOLDER1//
+     &		     NEWS_FOLDER1_DESCRIP)) THEN
+		   IER = 0
+		 ELSE IF (IER.EQ.0.AND..NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+		    IF (BTEST(NEWS_F1_FLAG,8)) THEN
+		       IF (NEWS_F1_LAST.NE.F1_NBULL.AND.
+     &			   F1_START.LE.F1_NBULL) THEN
+			  IF (NEWS_F1_FIRST.GT.F1_START.AND.
+     &			      NEWS_F1_FIRST.GT.F1_NBULL) THEN
+			     NEWS_F1_LAST = 0
+			     REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+			  END IF
+			  IF (NEWS_F1_LAST.LT.F1_NBULL) THEN
+			     CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),
+     &			      LOCAL_UPDATE,%DESCR(NEWS_FOLDER1_NUMBER))
+			  END IF
+		       END IF
+		    ELSE IF (((F1_START.NE.NEWS_F1_START.OR.
+     &			F1_NBULL.NE.NEWS_F1_NBULL).AND.F1_START.GT.0).OR.
+     &			NEWS_F1_COUNT.NE.F1_COUNT) THEN
+		       CALL SYS_BINTIM('-',F1_NEWEST_BTIM)
+		       CALL REWRITE_FOLDER_FILE_TEMP(IER1)
+		    END IF
+		 ELSE IF (IER.EQ.1.AND..NOT.BTEST(NEWS_F1_FLAG,8)) THEN
+		    DELETE (UNIT=7)
+		    IER = 0
+		 ELSE IF (IER.EQ.1) THEN
+		    IF (NEWS_F1_NBULL.LT.NEWS_F1_START
+     &			  .OR.NEWS_F1_START.EQ.0) THEN
+		       CALL CLOSE_BULLNEWS
+		       FOLDER_NUMBER = FOLDER1_NUMBER
+		       CALL SELECT_FOLDER(.FALSE.,IER1)
+		       IF (IER1) THEN
+			  CALL OPEN_BULLDIR_SHARED
+			  CALL READDIR(NEWS_F1_START,IER1)
+			  CALL CLOSE_BULLDIR
+			  IER1 = NEWS_F1_START+1.EQ.IER1
+		       END IF
+		       CALL OPEN_BULLNEWS_SHARED
+		       CALL READ_FOLDER_FILE_KEYNUM_TEMP(FOLDER_NUMBER,IER)
+		       IF (.NOT.IER1) DELETE (UNIT=7)
+		    END IF
+		    IER = 0
+		 END IF
+	      END IF
+	   END DO
+	END IF
+
+	CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,%DESCR(0))
+
+	CALL CLOSE_BULLNEWS
+	NEWSLIST = .FALSE.
+
+	IF (SYS_TRNLNM('BULL_NEWS_RECOUNT','DEFINED')) CALL RECOUNT
+
+	RETURN
+	END
+
+
+	SUBROUTINE LOWERCASE(INPUT)
+
+	CHARACTER*(*) INPUT
+
+	DO I=1,LEN(INPUT)
+	   IF (INPUT(I:I).GE.'A'.AND.INPUT(I:I).LE.'Z') THEN
+	      INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) - ICHAR('A') + ICHAR('a'))
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_POST(FILENAME,FILEOPEN,IER,SUBJECT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLNEWS.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /FOLLOWUP/ FOLLOWUP
+	CHARACTER*128 FOLLOWUP
+
+	COMMON /ZONE/ ZONE,LZONE
+	CHARACTER ZONE*4
+
+	COMMON /LOCALPOST/ LOCAL_POST
+	DATA LOCAL_POST /.FALSE./
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	COMMON /SENDER/ SENDER_LINE
+	CHARACTER*256 SENDER_LINE
+
+	COMMON /TEMP_INPUT/ GROUP_TEMP
+	CHARACTER GROUP_TEMP*256
+
+	COMMON /HEADER/ HEADER
+
+        COMMON /MAIL_INFO/ USE_INFROM
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	CHARACTER*(*) FILENAME,SUBJECT
+
+	CHARACTER RESPONSE*4
+
+	CHARACTER TODAY*24,UNAME*132
+	DATA UNAME /'()'/
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	COMMON /NEWS2BULL/ NEWS2BULL
+
+	DIMENSION NOW(2)
+
+	IER = 1
+
+	CREATE = FILENAME(:8).EQ.'newgroup'
+
+	IF (FILENAME.NE.'cancel') THEN
+	   IF (.NOT.FILEOPEN) THEN
+	      OPEN (UNIT=3,FILE=FILENAME,STATUS='OLD',IOSTAT=IER1)
+	      IF (IER1.NE.0) RETURN
+	   ELSE
+	      REWIND (UNIT=3)
+	   END IF
+
+	   IER1 = 0
+	   DO WHILE (IER1.EQ.0)
+	      READ (3,'(A)',IOSTAT=IER1) BUFFER
+	      IF (IER1.NE.0) GO TO 900
+	      IF (TRIM(BUFFER).GT.0) IER1 = 1
+	   END DO
+
+	   REWIND (UNIT=3)
+	END IF
+
+	IER = SYS$GETTIM(NOW)
+	CALL CONVERT_TO_GMT(NOW)
+	IER = SYS$ASCTIM(,TODAY,NOW,)
+
+	NEWS_MSGID = TODAY(:2)//TODAY(4:6)//TODAY(10:11)//'.'//
+     &		TODAY(13:14)//TODAY(16:17)//TODAY(19:20)//TODAY(22:23)
+	IF (NEWS_MSGID(:1).EQ.' ') NEWS_MSGID = NEWS_MSGID(2:)
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   IF (.NOT.NEWS_LOGIN()) GO TO 900
+	   IF (.NOT.NEWS_WRITE('POST')) GO TO 900
+	   IF (.NOT.NEWS_READ()) GO TO 900
+	   IF (BUFFER(:3).NE.'340') THEN
+	      WRITE (6,'('' ERROR: Posting not allowed.'')')
+	      GO TO 900
+	   END IF
+	ELSE
+	   I = INDEX(NEWS_MSGID,'.')
+	   LENGTH = 0
+	   OPEN (UNIT=8,FILE=NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//
+     &		NEWS_MSGID(:I-1)//
+     &		NEWS_MSGID(I+1:TRIM(NEWS_MSGID))//'.POST',IOSTAT=IER,
+     &		STATUS='NEW',DISPOSE='DELETE',RECL=256)
+	   IF (IER.NE.0) RETURN
+	   LOCAL_POST = .TRUE.
+	   CALL INIT_QUEUE(GROUP_LIST1,FOLDER)
+	   GROUP_LIST = GROUP_LIST1
+	END IF
+
+	IF (LPATH.EQ.0) CALL GET_PATHNAME
+
+	IF (FILENAME.EQ.'cancel') THEN 
+	   IF (.NOT.NEWS_WRITE('Newsgroups: junk')) GO TO 900
+	ELSE IF (REMOTE_SET.GE.3.OR.CREATE.OR.NEWS_FEED()) THEN
+	   IF (CREATE) THEN
+	      INPUT = 'Newsgroups: '//FILENAME(10:TRIM(FILENAME))
+	   ELSE IF (NEWS_FEED()) THEN
+	      INPUT = 'Newsgroups: '//FOLDER1_DESCRIP
+	   ELSE IF (TRIM(NEWSGROUPS).GT.0.AND.INCMD(:2).EQ.'RE') THEN
+	      IF (TRIM(FOLLOWUP).EQ.0) THEN
+		 INPUT = 'Newsgroups: '//NEWSGROUPS
+		 IF (INDEX(NEWSGROUPS,',').GT.0) THEN
+		    WRITE (6,'('' Warning: Original message was cross'',
+     &                       ''posted to the following news groups:'')')
+		    DO I=1,TRIM(NEWSGROUPS),PAGE_WIDTH
+                       WRITE (6,'(1X,A)') NEWSGROUPS(I:
+     &			I-1+MIN(PAGE_WIDTH,TRIM(NEWSGROUPS(I:))))
+		    END DO
+		    CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &			'Type Y if you want your reply crossposted also, '//
+     &			'N for no: (default = Y) ')
+		    IF (RESPONSE(:1).EQ.'n'.OR.RESPONSE(:1).EQ.'N') THEN
+		       INPUT = 'Newsgroups: '//FOLDER_NAME
+		    END IF
+		 END IF
+	      ELSE
+		 INPUT = 'Newsgroups: '//FOLLOWUP
+	      END IF
+	   ELSE
+	      INPUT = 'Newsgroups: '//FOLDER_NAME
+	   END IF
+	   IF (FILENAME.NE.'cancel'.AND..NOT.CREATE.AND.
+     &	       .NOT.NEWS_FEED()) THEN
+	      NGROUPS = 0
+	      IF (BTEST(FOLDER_FLAG,8)) THEN
+		 CALL WRITE_QUEUE(%VAL(GROUP_LIST),GROUP_LIST,FOLDER)
+		 NGROUPS = NGROUPS + 1
+	      END IF
+	      IF (CLI$PRESENT('GROUPS')) THEN
+		 CALL OPEN_BULLNEWS_SHARED
+		 FLEN = 0
+		 DO WHILE (CLI$GET_VALUE('GROUPS',GROUP_TEMP))
+		    IER = SYS_TRNLNM(GROUP_TEMP,GROUP_TEMP)
+		    DO WHILE (TRIM(GROUP_TEMP).GT.0)
+		       COMMA = INDEX(GROUP_TEMP,',')
+		       IF (COMMA.GT.0) THEN
+			  FOLDER1_NAME = GROUP_TEMP(1:COMMA-1)
+			  GROUP_TEMP = GROUP_TEMP(COMMA+1:)
+		       ELSE
+			  FOLDER1_NAME = GROUP_TEMP
+			  GROUP_TEMP = ' '
+		       END IF
+		       CALL LOWERCASE(FOLDER1_NAME)
+		       FLEN = TRIM(FOLDER1_NAME)
+		       CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &			(FOLDER1_NAME(:FLEN),IER1)
+		       IF (IER1.EQ.0.AND..NOT.BTEST(FOLDER1_FLAG,9)
+     &			   .AND.TRIM(INPUT)+FLEN+1.LE.LEN(INPUT).AND.
+     &			   INDEX(INPUT,FOLDER1_NAME(:FLEN)//',').EQ.0.AND.
+     &			   INPUT(:TRIM(INPUT)).NE.FOLDER1_NAME(:FLEN)) THEN
+			  INPUT = INPUT(:TRIM(INPUT))//
+     &				  ','//FOLDER1_NAME(:FLEN)
+			  IF (BTEST(FOLDER1_FLAG,8).AND.LOCAL_POST) THEN
+			     CALL WRITE_QUEUE(%VAL(GROUP_LIST),
+     &				GROUP_LIST,FOLDER1)
+			     NGROUPS = NGROUPS + 1
+			  END IF
+		       ELSE
+			  WRITE (6,'(1X,A,'' is not a valid news group.'')')
+     &				FOLDER1_NAME(:FLEN)
+			  CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &			   'Do you still want to specify it? (default = Y) ')
+			  IF (RESPONSE(:1).NE.'n'.AND.
+     &			      RESPONSE(:1).NE.'N') THEN
+			     INPUT = INPUT(:TRIM(INPUT))//
+     &				  ','//FOLDER1_NAME(:FLEN)
+			  END IF
+		       END IF
+		    END DO
+		 END DO
+		 CALL CLOSE_BULLNEWS
+	      END IF
+	   END IF
+	   IF (.NOT.NEWS_WRITE(INPUT(:TRIM(INPUT)))) GO TO 900
+	END IF
+	ATSIGN = INDEX(PATHNAME,'@')
+	PCSIGN = INDEX(PATHNAME,'%')
+	CALL LOWERCASE(USERNAME)
+	IF (FILENAME.EQ.'cancel'.AND.SUBJECT(:6).EQ.'CanceL') THEN
+	   IF (.NOT.NEWS_WRITE('Path: cyberspam!usenet')) GO TO 900
+	ELSE
+	   IF (PCSIGN.GT.0) THEN
+	      IF (.NOT.NEWS_WRITE('Path: '//PATHNAME(ATSIGN+1:LPATH)//'!'
+     &	        //PATHNAME(PCSIGN+1:ATSIGN-1)//'!'
+     &	        //USERNAME(:TRIM(USERNAME)))) GO TO 900
+	   ELSE
+	      IF (.NOT.NEWS_WRITE('Path: '//PATHNAME(ATSIGN+1:LPATH)//'!'
+     &	        //USERNAME(:TRIM(USERNAME)))) GO TO 900
+	   END IF
+	END IF
+	IF (UNAME.EQ.'()') CALL GET_UNAME(UNAME)
+
+	IF (FILENAME.NE.'cancel') THEN
+	   FROM_LINE = USERNAME(:TRIM(USERNAME))//PATHNAME(:LPATH)//
+     &			UNAME(:TRIM(UNAME))
+	   IF (USE_INFROM) THEN
+	      IF (INDEX(INFROM,'::').GT.0) THEN
+		 IF (INDEX(INFROM,' ').GT.0) 
+     &		    INFROM = INFROM(:INDEX(INFROM,' ')-1)
+		 INFROM = INFROM(INDEX(INFROM,'::')+2:TRIM(INFROM))//
+     &		      	  PATHNAME(:LPATH)
+	      ELSE IF (INDEX(INFROM,'@').EQ.0) THEN 
+		 INFROM = INFROM(:TRIM(INFROM))//PATHNAME(:LPATH)
+	      END IF
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED').AND.
+     &	            SYS_TRNLNM('MX_REPLY_TO',INFROM)) THEN
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED').AND.
+     &	            SYS_TRNLNM('PMDF_REPLY_TO',INFROM)) THEN
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE IF (SYS_TRNLNM('MULTINET_ROOT','DEFINED').AND.  
+     &	            SYS_TRNLNM('MULTINET_SMTP_REPLY_TO',INFROM)) THEN
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE
+	      IF (.NOT.NEWS_WRITE('From: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   END IF
+	   CALL STR$UPCASE(FROM_LINE,FROM_LINE)
+	   FROM_LINE = FROM_LINE(:TRIM(USERNAME)+LPATH)//UNAME(:TRIM(UNAME))
+	   CALL STR$UPCASE(USERNAME,USERNAME)
+	ELSE IF (REMOTE_SET.EQ.3) THEN
+	   IF (SENDER_LINE.NE.' ') THEN 
+	      IF (.NOT.NEWS_WRITE(SENDER_LINE(:TRIM(SENDER_LINE))))
+     &	         GO TO 900
+	   ELSE
+	      IF (.NOT.NEWS_WRITE(FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   END IF
+	ELSE
+	   HEADER_SAVE = HEADER
+	   HEADER = .TRUE.
+	   CALL OPEN_BULLFIL_SHARED
+	   ILEN = LINE_LENGTH + 1
+	   DO WHILE (ILEN.GT.0)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      ILEN = TRIM(INPUT)
+	      IF (INPUT(:5).EQ.'From:') THEN
+		 GROUP_TEMP = INPUT
+	      ELSE IF (INPUT(:7).EQ.'Sender:') THEN
+		 GROUP_TEMP = 'From:'//INPUT(8:)
+		 ILEN = 0
+	      END IF
+	   END DO
+	   ILEN = TRIM(GROUP_TEMP)
+	   IF (ILEN.NE.0) THEN
+	      IF (.NOT.NEWS_WRITE(GROUP_TEMP(:ILEN))) RETURN
+	   END IF
+	   CALL CLOSE_BULLFIL
+	   HEADER = HEADER_SAVE
+	END IF
+
+	IF (FILENAME.EQ.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Subject: cancel <'//
+     &	    MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) GO TO 900
+	ELSE IF (TRIM(SUBJECT).EQ.0) THEN
+	   IF (.NOT.NEWS_WRITE('Subject: (none)'))
+     &	      GO TO 900
+	ELSE
+	   IF (.NOT.NEWS_WRITE('Subject: '//SUBJECT(:TRIM(SUBJECT))))
+     &	      GO TO 900
+	END IF
+	SUBJECT_LINE = SUBJECT
+
+	IF (INCMD(:2).EQ.'RE') THEN
+	   IF (.NOT.NEWS_WRITE('References: '//REFERENCES(:LREF)))
+     &	      GO TO 900
+	END IF
+
+	IF (NGROUPS.GT.0) THEN
+	   FROM = USERNAME
+	   DESCRIP = SUBJECT
+	END IF
+
+	IF (FILENAME.NE.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Message-ID: <'//NEWS_MSGID(:
+     &	       TRIM(NEWS_MSGID))//PATHNAME(:LPATH)//'>')) GO TO 900
+	ELSE
+	   IF (.NOT.NEWS_WRITE('Message-ID: <cancel.'//
+     &	       MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) GO TO 900
+	END IF
+	NEWS_MSGID = NEWS_MSGID(:TRIM(NEWS_MSGID))//PATHNAME(:LPATH)
+
+	IF (LORGAN.EQ.0) THEN
+	   IF (SYS_TRNLNM('BULL_NEWS_ORGANIZATION','DEFINED')) THEN
+	      IER1 = SYS_TRNLNM('BULL_NEWS_ORGANIZATION',ORGANIZATION)
+	   END IF
+	   LORGAN = TRIM(ORGANIZATION)
+	END IF
+
+	IF (FILENAME.NE.'cancel'.AND.LORGAN.GT.0) THEN
+	   IF (.NOT.NEWS_WRITE('Organization: '//ORGANIZATION(:LORGAN)))
+     &		GO TO 900
+	ELSE IF (FILENAME.EQ.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Organization: cancel'))
+     &		GO TO 900
+	END IF
+
+	IF (.NOT.USE_INFROM.OR.COMPARE_DATE(TODAY(:11),DATE).GT.13) THEN
+	   DATE = TODAY(:11)
+	   TIME = TODAY(13:20)//'.00'
+	   TODAY = TODAY(:2)//' '//TODAY(4:6)//' '//TODAY(8:20)
+	   IF (TODAY(1:1).EQ.' ') TODAY = TODAY(2:)
+	   IF (.NOT.NEWS_WRITE('Date: '//TODAY(:TRIM(TODAY))//' '//
+     &		ZONE(:LZONE))) GO TO 900
+	ELSE
+	   CALL COPY2(NOW,MSG_BTIM)
+	   CALL CONVERT_TO_GMT(NOW)
+	   IER = SYS$ASCTIM(,TODAY,NOW,)
+	   DATE = TODAY(:11)
+	   TIME = TODAY(13:20)//'.00'
+	   TODAY = DATE(:2)//' '//DATE(4:6)//' '//DATE(8:)
+	   IF (TODAY(1:1).EQ.' ') TODAY = TODAY(2:)
+	   IF (.NOT.NEWS_WRITE('Date: '//TODAY(:TRIM(TODAY))//' '//
+     &		TIME(:8)//' '//ZONE(:LZONE))) GO TO 900
+	   IER = SYS$ASCTIM(,TODAY,MSG_BTIM,)
+	   DATE = TODAY(:11)
+	   TIME = TODAY(13:20)//'.00'
+	END IF
+
+	INPUT_HEADER = .FALSE.
+
+	IF (.NOT.(CREATE.OR.FILENAME.EQ.'cancel')) THEN
+	   EXPR = NEWS_FEED().OR.USE_INFROM
+	   IF (.NOT.EXPR) EXPR = CLI$PRESENT('EXPIRATION')
+	   IF (EXPR) THEN
+	      CALL SYS_BINTIM(EXDATE//' '//EXTIME,NOW)
+	      CALL CONVERT_TO_GMT(NOW)
+	      IER = SYS$ASCTIM(,TODAY,NOW,)
+	      EXDATE = TODAY(:11)
+	      EXTIME = TODAY(13:20)
+	      I = INDEX(EXDATE,'-')
+	      IF (EXDATE(I+5:I+8).EQ.'2100') THEN ! Servers not Y21K compliant
+		 READ (DATE(8:11),'(I4)') J
+		 WRITE (EXDATE(I+5:I+8),'(I4)') J+10	! 10 years
+	      END IF
+	      IF (.NOT.NEWS_WRITE('Expires: '//EXDATE(FIRST_ALPHA(EXDATE):2)
+     &		   //' '//EXDATE(I+1:I+3)//' '//EXDATE(I+5:TRIM(EXDATE))
+     &		   //' '//EXTIME(:8)//' '//ZONE(:LZONE)))
+     &		   GO TO 900
+	   ELSE IF (REMOTE_SET.EQ.4) THEN
+	      IF (FOLDER_BBEXPIRE.GT.0) THEN
+		 CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      ELSE
+		 CALL GET_EXDATE(EXDATE,NEWS_EXPIRE_DEFAULT)
+	      END IF
+	      EXTIME = '00:00:00.00'
+	   END IF
+	   IF (.NOT.NEWS_FEED()) THEN
+	      IF (CLI$GET_VALUE('FOLLOWUP',GROUP_TEMP)) THEN
+	         CALL LOWERCASE(GROUP_TEMP)
+	         IF (.NOT.NEWS_WRITE('Followup-To: '
+     &		     //GROUP_TEMP(:TRIM(GROUP_TEMP)))) GO TO 900
+	      END IF
+	   END IF
+	END IF
+
+	IF (CREATE) THEN
+	   IF (.NOT.NEWS_WRITE('Control: '//FILENAME(:TRIM(FILENAME))))
+     &		 RETURN
+	END IF
+
+	IF (NEWS_FEED().OR.NEWS2BULL) THEN
+	   IF (LPATH.EQ.0) CALL GET_PATHNAME
+	   IF (.NOT.NEWS_WRITE('X-Newsreader: News2bull')) GO TO 900
+	END IF
+
+	IF (FILENAME.EQ.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Control: cancel <'
+     &		//MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) RETURN
+	   IF (.NOT.NEWS_WRITE(' ')) RETURN
+	   IF (.NOT.NEWS_WRITE('cancel <'
+     &		//MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) RETURN
+	   IF (SUBJECT(:6).EQ.'CanceL') THEN
+	      IF (SUBJECT.EQ.'CanceL') THEN
+	         WRITE (6,1055)
+	         ILEN = LINE_LENGTH + 1		! Length of input line
+	         DO WHILE (ILEN.GE.0)		! Input until no more input
+	            CALL GET_LINE(INPUT,ILEN)	! Get input line
+	            IF (ILEN.GT.LINE_LENGTH) THEN  ! Input line too long
+		       WRITE(6,'('' ERROR: Input line length > '',I,
+     &			      ''.  Reinput:'')') LINE_LENGTH
+	            ELSE IF (ILEN.GE.0) THEN	! If good input line entered
+	    	       IF (.NOT.NEWS_WRITE(INPUT(:ILEN))) RETURN
+	            END IF
+	         END DO
+	      ELSE
+		 IF (.NOT.NEWS_WRITE(SUBJECT(7:TRIM(SUBJECT)-6))) RETURN
+	      END IF
+	   END IF
+	   IF (.NOT.NEWS_WRITE('.')) RETURN
+	   IF (REMOTE_SET.EQ.3) THEN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (BUFFER(:3).EQ.'240') IER = 0
+	   ELSE
+	      CLOSE (UNIT=8,STATUS='SAVE')
+	      IER = 0
+	   END IF
+	   CALL STR$UPCASE(USERNAME,USERNAME)
+	   LOCAL_POST = .FALSE.
+	   RETURN
+	END IF
+
+	IF (.NOT.INPUT_HEADER) THEN
+	   IF (.NOT.NEWS_WRITE(' ')) GO TO 900
+	END IF
+
+	IER1 = 0
+	DO WHILE (IER1.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER1) ILEN,BUFFER
+	   IF (BUFFER(:ILEN).EQ.'.') THEN
+	      BUFFER = '..'
+	      ILEN = 2
+	   END IF
+	   IF (IER1.EQ.0) THEN
+	      IF (.NOT.NEWS_WRITE(BUFFER(:ILEN))) GO TO 900
+	   END IF
+	END DO
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   IF (.NOT.NEWS_WRITE('.')) GO TO 900
+	   IF (.NOT.NEWS_READ()) GO TO 900
+	   IF (BUFFER(:3).EQ.'240') THEN
+	      IER = 0
+	   ELSE
+	      WRITE (6,'('' ERROR: Server rejected your posting:'')')
+	      WRITE (6,'(1X,A)') BUFFER(SB:MIN(79+SB,EB))
+	      IF (INDEX(BUFFER(SB:EB),'new text').GT.0) THEN
+		 WRITE (6,'('' Use /INDENT to change indentation'',$)')
+		 WRITE (6,'(''+ character. See Manager for permanent'',$)')
+		 WRITE (6,'(''+ change.'')')
+	      END IF
+	   END IF
+	ELSE
+	   LENGTH = (LENGTH+127)/128
+	   GROUP_LIST = GROUP_LIST1
+	   FOLDER_NUMBER_SAVE = FOLDER_NUMBER
+	   SAVE_BULL_POINT = BULL_POINT
+	   OLD_NBULL = NBULL
+	   DO I=NGROUPS,1,-1
+	      CALL READ_QUEUE(%VAL(GROUP_LIST),GROUP_LIST,FOLDER1)
+	      FOLDER_NUMBER = -1
+	      OLD_NBULL = NBULL
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (IER) THEN
+		 CALL ADD_LOCAL_NEWS(8)
+		 CALL ADD_TAG(IER,2)
+		 IF (NEWS_FIND_SUBSCRIBE().LT.FOLDER_MAX) THEN
+		    CALL NEWS_GET_NEWEST_MESSAGE(IER1)
+		    IF (IER1.EQ.0.OR.IER1.EQ.OLD_NBULL+1) THEN
+		       CALL NEWS_UPDATE_NEWEST_MESSAGE(OLD_NBULL+1)
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (FOLDER_NUMBER.NE.FOLDER_NUMBER_SAVE) THEN
+	      FOLDER_NUMBER = FOLDER_NUMBER_SAVE
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	   END IF
+	   BULL_POINT = SAVE_BULL_POINT
+	   IF (.NOT.NEWS_WRITE('.')) GO TO 900
+	   CLOSE (UNIT=8,STATUS='SAVE')
+	   IER = 0
+	END IF
+
+900	IF (FILENAME.NE.'cancel'.AND..NOT.FILEOPEN) CLOSE (UNIT=3)
+	CALL STR$UPCASE(USERNAME,USERNAME)
+
+	LOCAL_POST = .FALSE.
+
+1055	FORMAT(' State reason for deleting message not owned by you:')
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_PATHNAME
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	IF (NEWS_GETHOSTNAME(PATHNAME).EQ.-1) THEN
+	   IER = SYS_TRNLNM_SYSTEM('MX_NODE_NAME',PATHNAME)
+	   IF (.NOT.IER)
+     &		IER = SYS_TRNLNM_SYSTEM('ARPANET_HOST_NAME',PATHNAME)
+	   IF (.NOT.IER)
+     &		IER = SYS_TRNLNM_SYSTEM('INTERNET_HOST_NAME',PATHNAME)
+	   IF (.NOT.IER) THEN
+	      WRITE (6,'('' ERROR: Cannot find local host name.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	IF (ALPHA(PATHNAME(:1))) PATHNAME = '@'//PATHNAME
+
+	CALL LOWERCASE(PATHNAME)
+	LPATH = TRIM(PATHNAME)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST_NEWS(NAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) NAME
+
+	TEST_NEWS = .FALSE.
+	MAYBE_NEWS = .FALSE.
+
+	DO I=1,LEN(NAME)
+	   IF (NAME(I:I).GE.'A'.AND.NAME(I:I).LE.'Z') RETURN
+	   IF (NAME(I:I).GE.'a'.AND.NAME(I:I).LE.'z') MAYBE_NEWS = .TRUE.
+	END DO
+
+	TEST_NEWS = MAYBE_NEWS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_LOCAL_NEWS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /LOCAL_UPDATE/ LOCAL_UPDATE1
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER CNUM*4,NUMBER*8
+	EQUIVALENCE (CNUM,NUM)
+
+	CALL INIT_QUEUE(LOCAL_UPDATE1,CNUM)
+
+	LOCAL_UPDATE = LOCAL_UPDATE1
+
+	CALL READ_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,CNUM)
+	IF (NUM.EQ.0) RETURN
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	DO WHILE (NUM.GT.0)
+	   CALL READ_FOLDER_FILE_KEYNUM_TEMP(NUM,IER)
+	   IF (IER.EQ.0) THEN
+	      CALL CLOSE_BULLNEWS
+	      CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      LAST = F1_NBULL
+	      FIRST = F1_START
+	      IF (IER.EQ.0) THEN
+		 FOLDER_COM = FOLDER1_COM
+		 REMOTE_SET = 3
+		 CALL OPEN_BULLDIR_SHARED
+		 INCMD = 'READ'	  ! REMOTE_GET_HEADER uses NEXT otherwise
+		 I = F_LAST + 1
+		 IER = I - 1
+		 DO WHILE (I.NE.IER.AND.I.LE.LAST)
+		    CALL READDIR(I,IER)
+		    I = I + 1
+		 END DO
+		 CALL CLOSE_BULLDIR
+		 CALL OTS$CVT_L_TI(I-1,NUMBER,,,)
+		 INCMD = 'COPY/ORIGINAL '//FOLDER(:TRIM(
+     &			FOLDER))//' '//NUMBER//'-LAST'
+		 CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+		 CALL MOVE(.FALSE.)
+		 CALL OPEN_BULLNEWS_SHARED
+		 IF (REMOTE_SET.EQ.4) THEN
+		    NEW_F_COUNT = F_COUNT
+		    NEW_NEWS_F_END = NEWS_F_END
+		    CALL READ_FOLDER_FILE_KEYNUM(NUM,IER)
+		    CALL GET_MSGKEY(NEWEST_EXBTIM,NEWS_F_EXPIRED_DATE)
+		    CALL COPY2(F_NEWEST_BTIM,NEWEST_MSGBTIM)
+		    IF (F_START.EQ.0.AND.NBULL.GT.0) F_START = 1
+		    IF (NEW_NEWS_F_END.GT.NEWS_F_END) THEN
+		       NEWS_F_END = NEW_NEWS_F_END
+		       F_NBULL = NEW_NEWS_F_END
+		       F_COUNT = NEW_F_COUNT
+		    END IF
+		    F_LAST = LAST
+		    NEWS_F_FIRST = FIRST
+		    CALL REWRITE_FOLDER_FILE(IER)
+		 END IF
+	      END IF
+	   END IF
+	   CALL READ_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,CNUM)
+	   IF (NUM.EQ.0) THEN
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS2BULL(RECLAIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLCP_NEWS/ BULLCP_NEWS
+	DATA BULLCP_NEWS /.FALSE./
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER FOLDER_SAVE*44,BBOARD_SAVE*12
+
+	CHARACTER*8 NUMBER
+
+	DIMENSION NOW(2)
+
+	BULLCP_NEWS = .TRUE.
+
+	IER = SYS$GETTIM(NOW)
+
+	CALL ALLPRIV
+
+	CALL DELETE_EXPIRED_NEWS(RECLAIM)
+
+	IF (RECLAIM) CALL EXIT
+
+	CALL SEND_POST
+	IF (ALT_SET()) CALL UNSET_ALT
+
+	CALL NEWS_LIST
+
+	CALL UPDATE_LOCAL_NEWS
+
+	CALL INIT_QUEUE(FOLDER_Q1,FOLDER_COM)
+
+	FOLDER_Q = FOLDER_Q1
+
+	CALL OPEN_BULLFOLDER_SHARED             ! Get folder file
+
+	NUM_FOLDERS = 0
+	IER = 0
+	DO WHILE (IER.EQ.0)                     ! Find folders with news feed
+	   CALL READ_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) THEN
+	      IF (NEWS_FEED()) THEN
+		 NUM_FOLDERS = NUM_FOLDERS + 1
+		 CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFOLDER                   ! We don't need file anymore
+
+	IF (NUM_FOLDERS.EQ.0.OR..NOT.NEWS_LOGIN()) CALL EXIT
+
+	FOLDER_Q = FOLDER_Q1
+	POINT_FOLDER = 0
+	DO WHILE (POINT_FOLDER.LT.NUM_FOLDERS)
+	   POINT_FOLDER = POINT_FOLDER + 1
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   FOLDER_SAVE = FOLDER
+	   BBOARD_SAVE = FOLDER_BBOARD
+	   FOLDER_DESCRIP = FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,'<')+1:)
+	   FOLDER_DESCRIP = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,'>')-1)
+	   IF (IER) THEN
+	      SAVE_LAST = F_LAST
+	      CALL OPEN_BULLNEWS_SHARED
+	      FOLDER1 = FOLDER_DESCRIP(:TRIM(FOLDER_DESCRIP))
+	      CALL READ_FOLDER_FILE_KEYNAME
+     &		(FOLDER_DESCRIP(:TRIM(FOLDER_DESCRIP)),IER)
+	      CALL CLOSE_BULLNEWS
+	      FOLDER1_DESCRIP = FOLDER_DESCRIP
+	      IF (IER.EQ.0) CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      IF (IER.EQ.0) FOLDER_COM = FOLDER1_COM
+	      IF (IER.EQ.0.AND.BBOARD_SAVE.EQ.'NONE') THEN
+		 SAVE_LAST = F_NBULL
+		 CALL OPEN_BULLFOLDER
+		 CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER1)
+		 F_LAST = SAVE_LAST
+		 FOLDER_BBOARD = 'NONEFEED'
+		 CALL REWRITE_FOLDER_FILE(IER1)
+		 CALL CLOSE_BULLFOLDER
+	      ELSE IF (IER.EQ.0.AND.F_NBULL.NE.SAVE_LAST.AND.
+     &		  F_NBULL.GE.F_START) THEN
+	         IF (FOLDER_BBOARD.EQ.'NONEFEED') THEN
+		    CALL SETUSER('SYSTEM')
+	         ELSE
+		    CALL SETUSER(FOLDER_BBOARD)
+	         END IF
+		 REMOTE_SET = 3
+		 IF (SAVE_LAST.GT.F_NBULL.AND.F_START.EQ.1)
+     &			SAVE_LAST = F_START-1
+		 SAVE_LAST = MAX(F_START-1,SAVE_LAST)
+		 CALL OTS$CVT_L_TI(SAVE_LAST+1,NUMBER,,,)
+		 INCMD = 'COPY/LOCAL/ORIGINAL '//FOLDER_SAVE(:TRIM(
+     &			FOLDER_SAVE))//' '//NUMBER//'-LAST'
+		 SAVE_LAST = F_NBULL
+		 CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+		 CALL MOVE(.FALSE.)
+		 CALL OPEN_BULLFOLDER
+		 CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER1)
+		 IF (IER1.EQ.0) THEN
+		    F_LAST = SAVE_LAST
+		    CALL REWRITE_FOLDER_FILE(IER1)
+		 END IF
+		 CALL CLOSE_BULLFOLDER
+	         CALL SETUSER(USERNAME)
+	      END IF
+	   END IF
+	END DO
+
+	CALL EXIT
+	END
+
+
+
+	SUBROUTINE DATE_TIME(TIME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MONTHS/ MONTH
+	CHARACTER*36 MONTH
+	DATA MONTH/'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'/
+
+	CHARACTER*(*) TIME
+
+	NMONTH = (INDEX(MONTH,TIME(4:6))+2)/3
+
+	IF (TIME(1:1).EQ.' ') TIME(1:1) = '0'
+
+	TIME = TIME(10:11)//CHAR(ICHAR('0')+NMONTH/10)//CHAR(ICHAR('0')+
+     &		 MOD(NMONTH,10))//TIME(1:2)//' '//TIME(13:14)//
+     &		 TIME(16:17)//TIME(19:20)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ALLPRIV
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	PROCPRIV(1) = -1
+	PROCPRIV(2) = -1
+	NEEDPRIV(1) = -1
+	NEEDPRIV(2) = -1
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_NEW_FOLDER
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1) NEWS_FOLDER_COM
+
+	NEWS_FOLDER1 = FOLDER1
+	NEWS_FOLDER1_DESCRIP = FOLDER1_DESCRIP(26:)
+
+	DO WHILE (IER.EQ.0)
+	   READ (7,IOSTAT=IER,KEYEQ=NEWS_F_COUNT,KEYID=1)
+	   IF (IER.EQ.0) NEWS_F_COUNT = NEWS_F_COUNT + 1
+	END DO
+
+	NEWS_FOLDER1_NUMBER = NEWS_F_COUNT
+	CALL SYS_BINTIM('-',NEWS_F1_NEWEST_BTIM)
+	WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+
+	READ (7,KEYEQ=1000,KEYID=1) NEWS_FOLDER1_COM
+	NEWS_F1_COUNT = NEWS_F_COUNT
+	REWRITE (7) NEWS_FOLDER1_COM
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SUBSCRIBE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.LT.3) THEN
+	   WRITE (6,'('' ERROR: Selected folder is not a news folder.'')')
+	   RETURN
+	END IF
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.NEWS_FOLDER_NUMBER.AND.
+     &		LAST_NEWS_READ2(1,I).NE.0.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: Cannot subscribe.  You have '',
+     &		    '' reached the news folder limit of '',I,''.'')')
+     &		    FOLDER_MAX-1
+	   RETURN
+	ELSE IF (LAST_NEWS_READ2(1,I).EQ.NEWS_FOLDER_NUMBER) THEN
+	   WRITE (6,'('' You are already subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   RETURN
+	ELSE
+	   WRITE (6,'('' You are now subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	END IF
+
+	CALL UPDATE_USERINFO
+
+	CALL OPEN_BULLNEWS_SHARED
+	DO J=I,1,-1
+	   IF (J.GT.1) THEN
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(
+     &		 ZEXT(LAST_NEWS_READ2(1,J-1)),IER)
+	      IF (FOLDER_DESCRIP.LT.FOLDER1_DESCRIP) THEN
+		 CALL COPY2(LAST_NEWS_READ(1,J),LAST_NEWS_READ(1,J-1))
+	      END IF
+	   END IF
+	   IF (FOLDER_DESCRIP.GT.FOLDER1_DESCRIP.OR.J.EQ.1) THEN
+	      LAST_NEWS_READ2(1,J) = NEWS_FOLDER_NUMBER
+	      IF (F_START.LE.F_NBULL) THEN
+		 LAST_NEWS_READ2(2,J) = MIN(8191,F_NBULL-(F_START-1))
+		 LAST_NEWS_READ(2,J) = F_START - 1
+	      ELSE
+		 LAST_NEWS_READ2(2,J) = 0
+		 LAST_NEWS_READ(2,J) = F_NBULL
+	      END IF
+	      CALL CLOSE_BULLNEWS
+	      CALL LIB$MOVC3(8*FOLDER_MAX,LAST_NEWS_READ,OLD_LAST_NEWS_READ)
+	      CALL UPDATE_USERINFO_NEWS_ALWAYS
+	      RETURN
+	   END IF
+	END DO
+
+	END
+
+
+
+
+
+	SUBROUTINE UNSUBSCRIBE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_EXPIRED
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: You are not subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLINF_SHARED
+	DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY='*PERM',IOSTAT=IER) TEMP_USER,INF_REC
+	END DO
+	IF (IER.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      INF_REC(1,I) = 0
+	      INF_REC(2,I) = 0
+	   END DO
+	END IF
+	CALL CLOSE_BULLINF
+
+	I = 1
+	DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	IF (I.LE.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: Folder is permanent and cannot not be'',
+     &		      '' unsubscribed.'')')
+	   RETURN
+	END IF
+
+	WRITE (6,'('' You are now no longer subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+
+	CALL UPDATE_USERINFO
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	DO J=I,FOLDER_MAX-2
+	   CALL COPY2(LAST_NEWS_READ(1,J),LAST_NEWS_READ(1,J+1))
+	END DO
+
+	LAST_NEWS_READ(1,FOLDER_MAX-1) = 0
+	LAST_NEWS_READ(2,FOLDER_MAX-1) = 0
+
+	CALL FREE_TAGS(I)
+
+	IF (NINCLUDE.GT.0) THEN
+	   WRITE (6,'('' Note: Excludes and/or '',
+     &		      ''threads exist for this group.'')')
+	   WRITE (6,'('' Type EXCLUDE/DISABLE/ALL to remove them.'')')
+	END IF
+
+	CALL LIB$MOVC3(8*FOLDER_MAX,LAST_NEWS_READ,OLD_LAST_NEWS_READ)
+
+	CALL UPDATE_USERINFO_NEWS_ALWAYS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_GET_NEWEST_MESSAGE(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IER = LAST_NEWS_READ(2,I) + 1
+
+	IF (IER.EQ.0) IER = 1           ! None read yet.
+
+	IF (I.GT.FOLDER_MAX-1.OR.IER.GT.F_NBULL) THEN
+	   IER = 0
+	   RETURN
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_GET_NEWEST_MESSAGE1(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE1()
+
+	IER = LAST_NEWS_READ(2,I) + 1
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   IER = 0
+	   RETURN
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_UPDATE_NEWEST_MESSAGE(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	IF (NUMBER.GT.LAST_NEWS_READ(2,I).OR.(LAST_NEWS_READ(2,I)
+     &	 .GT.NEWS_F_NBULL.AND.F_START.LE.F_NBULL)) THEN
+	   LAST_NEWS_READ(2,I) = NUMBER
+	   LAST_NEWS_READ2(2,I) = MIN(8191,F_NBULL-NUMBER)
+     &			.OR.(LAST_NEWS_READ2(2,I).AND.'E000'X)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE NEWS_GET_SUBSCRIBE(SUBNUM,SUBMSG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (SUBNUM.EQ.0) THEN
+	   COUNT = 0
+	   SUBMSG = LAST_NEWS_READ(2,1)
+	   RETURN
+	ELSE IF (SUBNUM.EQ.-1) THEN
+	   DO J=COUNT,FOLDER_MAX-1
+	      CALL COPY2(LAST_NEWS_READ(1,J),LAST_NEWS_READ(1,J+1))
+	   END DO
+
+	   LAST_NEWS_READ(1,FOLDER_MAX-1) = 0
+	   LAST_NEWS_READ(2,FOLDER_MAX-1) = 0
+	ELSE IF (SUBNUM.GT.0) THEN
+	   COUNT = COUNT + 1
+	END IF
+
+	IF (COUNT.LE.FOLDER_MAX-1) THEN
+	   SUBNUM = LAST_NEWS_READ2(1,COUNT)
+	   SUBMSG = LAST_NEWS_READ(2,COUNT)
+	ELSE
+	   SUBNUM = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS_NEW_NOTIFICATION(MESSAGES)
+C
+C  SUBROUTINE NEWS_NEW_NOTIFICATION
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /LOGIN_BTIM/ LOGIN_BTIM_SAVE(2)
+
+	MESSAGES = .FALSE.
+
+	IF (.NOT.SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) RETURN
+
+	CALL NEWS_GET_SUBSCRIBE(0,MSGNUM)
+
+	CALL OPEN_BULLNEWS_SHARED
+	SUBNUM = 1
+
+	FOLDER_DESCRIP = ' '
+	REORDER = 0
+	DO WHILE (SUBNUM.GT.0)
+	   IER = 1
+	   DO WHILE (SUBNUM.NE.0.AND.IER.NE.0)
+	      CALL NEWS_GET_SUBSCRIBE(SUBNUM,MSGNUM)
+	      FOLDER1_DESCRIP = FOLDER_DESCRIP
+	      IF (SUBNUM.NE.0) THEN
+		 CALL READ_FOLDER_FILE_KEYNUM(SUBNUM,IER)
+		 IF (IER.EQ.0) FOLDER_NUMBER = SUBNUM
+		 UNLOCK 7
+		 IF (FOLDER1_DESCRIP.GT.FOLDER_DESCRIP) REORDER = 1
+		 IF (IER.EQ.0.AND.
+     &			MSGNUM.GT.F_NBULL.AND.F_START.LE.F_NBULL) THEN
+		    CALL NEWS_UPDATE_NEWEST_MESSAGE(F_START-1)
+		    CALL UPDATE_USERINFO
+		    IF (F_START.EQ.0) IER = 1
+		 ELSE IF (IER.NE.0) THEN
+		    SUBNUM = -1
+		 ELSE IF (MSGNUM.GE.F_NBULL.OR.F_NBULL.EQ.0.OR.
+     &			  F_START.GT.F_NBULL) THEN
+		    IER = 1
+		 END IF
+	      END IF
+	      IF (IER.EQ.0.AND.SUBNUM.GT.0) THEN
+		 IF (READIT.EQ.1) THEN
+		    IF (.NOT.TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER).AND.
+     &			.NOT.TEST_SET_FLAG(NEWS_FOLDER_NUMBER)) THEN
+		       IER = 1
+		    ELSE IF (.NOT.TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER).OR.
+     &			.NOT.TEST_SET_FLAG(NEWS_FOLDER_NUMBER).OR.
+     &			NEW_FLAG(2).NE.-1) THEN
+		       DIFF = COMPARE_BTIM(LOGIN_BTIM_SAVE,F_NEWEST_BTIM)
+		       IF (DIFF.GT.0) IER = 1
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (READIT.EQ.0.AND.SUBNUM.GT.0) THEN
+	      WRITE (6,'('' There are new messages in folder '',
+     &		  A)') FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	      MESSAGES = .TRUE.
+	   ELSE IF (SUBNUM.GT.0) THEN
+	      IF (TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER)
+     &		  .AND.TEST_SET_FLAG(NEWS_FOLDER_NUMBER)) THEN
+		 WRITE (6,'('' There are new messages in folder ''
+     &		  A)') FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	      ELSE
+		 CALL CLOSE_BULLNEWS
+		 CALL SELECT_FOLDER(.FALSE.,IER1)
+		 IF (IER1) THEN
+		    CALL LOGIN_FOLDER
+		    IF (BULL_POINT.NE.-1) THEN
+		       NEWS_FOLDER_NUMBER = FOLDER_NUMBER
+		       IF (.NOT.TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER)) THEN
+			  SAVE_BULL_POINT = BULL_POINT
+			  REDO = .TRUE.
+			  DO WHILE (REDO)
+			     REDO = .FALSE.
+			     CALL READNEW(REDO)
+			     IF (REDO) CALL REDISPLAY_DIRECTORY
+			     BULL_POINT = SAVE_BULL_POINT
+			  END DO
+		       END IF
+		    END IF
+		 END IF
+		 CALL OPEN_BULLNEWS_SHARED
+	      END IF
+	   END IF
+	END DO
+
+	IF (REORDER.EQ.1) CALL REORDER_SUBSCRIBE
+
+	CALL CLOSE_BULLNEWS
+
+	RETURN
+	END
+
+
+	SUBROUTINE REORDER_SUBSCRIBE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.0)
+	   I = I + 1
+	END DO
+
+	I = I - 1
+
+	DO I1=1,I-1
+	   DO J=1,I-I1
+	      K = J + 1
+	      S1 = LAST_NEWS_READ2(1,J)
+	      S2 = LAST_NEWS_READ2(1,K)
+	      CALL READ_FOLDER_FILE_KEYNUM(S1,IER)
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(S2,IER1)
+	      IF (IER+IER1.EQ.0.AND.FOLDER1_DESCRIP.LT.FOLDER_DESCRIP) THEN
+		 DO L=1,2
+		    TEMP = LAST_NEWS_READ(L,J)
+		    LAST_NEWS_READ(L,J) = LAST_NEWS_READ(L,K)
+		    LAST_NEWS_READ(L,K) = TEMP
+		 END DO
+	      END IF
+	   END DO
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_SET_FLAG(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (NUMBER.GE.0.AND.NUMBER.LE.FOLDER_MAX-1) THEN
+	   TEST_SET_FLAG = TEST2(SET_FLAG,NUMBER)
+	   RETURN
+	END IF
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	TEST_SET_FLAG = .FALSE.
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	TEST_SET_FLAG = BTEST(LAST_NEWS_READ2(2,I),14)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_BRIEF_FLAG(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (NUMBER.GE.0.AND.NUMBER.LE.FOLDER_MAX-1) THEN
+	   TEST_BRIEF_FLAG = TEST2(BRIEF_FLAG,NUMBER)
+	   RETURN
+	END IF
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	TEST_BRIEF_FLAG = .FALSE.
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	TEST_BRIEF_FLAG = BTEST(LAST_NEWS_READ2(2,I),15)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_NOTIFY_FLAG(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (NUMBER.GE.0.AND.NUMBER.LE.FOLDER_MAX-1) THEN
+	   TEST_NOTIFY_FLAG = TEST2(NOTIFY_FLAG,NUMBER)
+	   RETURN
+	END IF
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	TEST_NOTIFY_FLAG = .FALSE.
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	TEST_NOTIFY_FLAG = BTEST(LAST_NEWS_READ2(2,I),13)
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_FIND_SUBSCRIBE()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.NEWS_FOLDER_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	NEWS_FIND_SUBSCRIBE = I
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_FIND_SUBSCRIBE1()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	NEWS_FIND_SUBSCRIBE1 = I
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS_SET_USER_FLAG(NOTIFY,READNEW,BRIEF)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: NEWS FOLDER is not subscribed.'')')
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLINF_SHARED
+	DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY='*PERM',IOSTAT=IER1) TEMP_USER,INF_REC
+	END DO
+	IF (IER1.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      INF_REC(1,I) = 0
+	      INF_REC(2,I) = 0
+	   END DO
+	END IF
+	CALL CLOSE_BULLINF
+
+	IP = 1
+	DO WHILE (INF_REC2(1,IP).NE.NEWS_FOLDER_NUMBER
+     &					.AND.IP.LE.FOLDER_MAX-1)
+	   IP = IP + 1
+	END DO
+
+	IER = .TRUE.
+
+	IF (IP.EQ.FOLDER_MAX) THEN
+	   PERM = .FALSE.
+	   IP = 1
+	ELSE
+	   PERM = .TRUE.
+	END IF
+
+	IF (NOTIFY.EQ.0) THEN
+	   IF (PERM.AND.BTEST(INF_REC2(2,IP),13)) THEN
+	      WRITE (6,'('' ERROR: NOTIFY is permanent for this folder.'')')
+	      RETURN
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),13)
+	   END IF
+	ELSE IF (NOTIFY.EQ.1) THEN
+	   LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),13)
+	   RETURN
+	ELSE IF (BRIEF.EQ.0.AND.READNEW.EQ.0.AND.PERM.AND.
+     &	    (BTEST(INF_REC2(2,IP),14).OR.BTEST(INF_REC2(2,IP),15))) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.0.AND.PERM.AND.
+     &	    (BTEST(INF_REC2(2,IP),14).AND.
+     &	    .NOT.BTEST(INF_REC2(2,IP),15))) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.1.AND.PERM.AND.
+     &	    (BTEST(INF_REC2(2,IP),14).XOR.BTEST(INF_REC2(2,IP),15))) THEN
+	   IER = .FALSE.
+	END IF
+
+	IF (IER) THEN
+	   IF (READNEW.EQ.1)
+     &		LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),14)
+	   IF (READNEW.EQ.0)
+     &		LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),14)
+	   IF (BRIEF.EQ.1)
+     &		LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),15)
+	   IF (BRIEF.EQ.0)
+     &		LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),15)
+	ELSE
+	   WRITE (6,'('' ERROR: PERMANENT flags exist for this folder.'')')
+	   WRITE (6,'('' Flags will be set to those permanent settings.'')')
+
+	   IF (BTEST(INF_REC2(2,IP),14)) THEN
+	      LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),14)
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),14)
+	   END IF
+
+	   IF (BTEST(INF_REC2(2,IP),15)) THEN
+	      LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),15)
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),15)
+	   END IF
+	END IF
+
+	CALL UPDATE_USERINFO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_LOCAL_NEWS(UNIT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	REWIND UNIT
+
+	CALL SYS_BINTIM(EXDATE//' '//EXTIME,EX_BTIM)
+
+	CALL OPEN_BULLDIR
+	CALL OPEN_BULLFIL
+	CALL SET_BULLFIL_UPDATE
+	OBLOCK = NBLOCK + 1
+	CALL STORE_BULL(TRIM(FROM_LINE)+6,'From: '//
+     &		    FROM_LINE(:TRIM(FROM_LINE)),OBLOCK)
+	IF (TRIM(SUBJECT_LINE).GT.LEN(DESCRIP)) THEN
+	   CALL STORE_BULL(TRIM(SUBJECT_LINE)+6,
+     &		'Subj: '//SUBJECT_LINE(:TRIM(SUBJECT_LINE)),OBLOCK)
+	END IF
+	CALL COPY_BULL(UNIT,1,OBLOCK,IER)
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	   RETURN
+	END IF
+	LENGTH = OCOUNT - (NBLOCK + 1) + 1
+	NBLOCK = NBLOCK + LENGTH + 1
+	SYSTEM = 0
+	CALL ADD_ENTRY
+	CALL CLOSE_BULLFIL
+	CALL UPDATE_NEWS_FOLDER
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_NEWS_FOLDER
+C
+C  SUBROUTINE UPDATE_NEWS_FOLDER
+C
+C  FUNCTION: Updates folder info due to new message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	NEW_NEWS_F_END = NEWS_F_END
+	NEW_F_COUNT = F_COUNT
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	IF (NEW_NEWS_F_END.GT.NEWS_F_END) THEN
+	   CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,F_NEWEST_BTIM)
+	   F_NBULL = NEW_NEWS_F_END
+	   NEWS_F_END = NEW_NEWS_F_END
+	   F_COUNT = NEW_F_COUNT
+	END IF
+
+	IF (F_START.EQ.0.AND.F_NBULL.GT.0) F_START = 1
+
+	CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),%DESCR(NEWEST_EXBTIM))
+	IF (COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).LT.0)
+     &		NEWS_F_EXPIRED_DATE = NEWS_EX_BTIM_KEY
+
+	CALL REWRITE_FOLDER_FILE(IER)
+
+	CALL CLOSE_BULLNEWS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SEND_POST
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /ALT_FOUND/ ALT_FOUND
+	CHARACTER*128 ALT_FOUND
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	COMMON /NEWSBULL/ NEWSBULL
+	DATA NEWSBULL /.FALSE./
+
+	CHARACTER FILE*132
+
+	C = 0
+
+	IF (.NOT.NEWS_LOGIN()) RETURN
+	DO WHILE (LIB$FIND_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &			//'*.POST*',FILE,C))
+50	   IF (.NOT.NEWS_WRITE('POST')) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:3).NE.'340') RETURN
+
+	   NEWSBULL = .FALSE.
+
+	   OPEN (UNIT=3,FILE=FILE,IOSTAT=IER,STATUS='OLD')
+	   DO WHILE (IER.EQ.0)
+	      READ (3,'(Q,A)',IOSTAT=IER) I,INPUT
+	      IF (IER.EQ.0) THEN
+		 IF (INPUT(:5).EQ.'From:') BULL_PARAMETER = INPUT(7:)
+		 IF (INDEX(INPUT,'X-Newsreader: News2bull').EQ.1) THEN 
+		    NEWSBULL = .TRUE.
+	            IF (LPATH.EQ.0) CALL GET_PATHNAME
+	            IF (.NOT.NEWS_WRITE('X-Newsreader: News2bull'
+     &	       		//' '//PATHNAME(:TRIM(PATHNAME)))) GO TO 100
+		 ELSE
+		    IF (.NOT.NEWS_WRITE(INPUT(:I))) GO TO 100
+		 END IF
+	      END IF
+	   END DO
+	   IF (INPUT.NE.'.') THEN
+	      IF (.NOT.NEWS_WRITE('.')) GO TO 100
+	   END IF
+	   IF (.NOT.NEWS_READ()) GO TO 100
+	   IF (BUFFER(:3).EQ.'441'.AND..NOT.ALT_SET()) THEN
+	      REWIND (UNIT=3)
+	      IER = 0
+	      DO WHILE (IER.EQ.0)
+	         READ (3,'(Q,A)',IOSTAT=IER) I,INPUT
+	         IF (IER.EQ.0.AND.INPUT(:12).EQ.'Newsgroups: ') THEN 
+		    CLOSE (UNIT=3)
+		    IF (TEST_ALT(INPUT(13:))) THEN
+			IF (SET_ALT(ALT_FOUND)) GOTO 50
+			GOTO 90
+	            END IF
+	            IER = 2
+	         END IF
+	      END DO
+	      CLOSE (UNIT=3)
+	   END IF
+	   IF (BUFFER(:3).NE.'240') THEN
+	      CLOSE (UNIT=3)
+	      IF (NEWSBULL.AND.INDEX(FILE,'POST_ERROR').EQ.0) THEN 
+		 CALL LIB$RENAME_FILE(FILE,'*.POST_ERROR',,,,,,,,,FILE)
+	         CALL SENDMAIL(FILE,'SYSTEM'
+     &			,'ERROR: Posting rejected: '//BUFFER(SB:EB),IER)
+		 NEWSBULL = .FALSE.
+	      ELSE IF (.NOT.NEWSBULL) THEN 
+	         CALL SENDMAIL(FILE,BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+     &			,'ERROR: Posting rejected: '//BUFFER(SB:EB),IER)
+	         OPEN (UNIT=3,FILE=FILE,IOSTAT=IER,STATUS='OLD')
+		 CLOSE (UNIT=3,STATUS='DELETE')
+	      END IF
+	   ELSE
+	      CLOSE (UNIT=3,STATUS='DELETE')
+	   END IF
+90	   IF (ALT_SET()) CALL UNSET_ALT
+	END DO
+
+100	CLOSE (UNIT=3)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_UNAME(UNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($MAILDEF)'
+
+	CHARACTER*(*) UNAME
+
+	CALL DISABLE_PRIVS
+
+	C = 0
+
+	STATUS = MAIL$USER_BEGIN(C,0,0)
+	IF (.NOT.STATUS) GO TO 100
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(LEN(UNAME),MAIL$_USER_PERSONAL_NAME,
+     &				%LOC(UNAME))
+	CALL END_ITMLST(GET_USER_ITMLST)
+
+	STATUS = MAIL$USER_GET_INFO(C,0,%VAL(GET_USER_ITMLST))
+	IF (.NOT.STATUS) GO TO 100
+
+	STATUS = MAIL$USER_END(C,0,0)
+	IF (.NOT.STATUS) GO TO 100
+
+100	CALL ENABLE_PRIVS
+
+	IER = SYS_TRNLNM('BULL_PERSONAL_NAME',UNAME)
+	
+	IF (UNAME.EQ.'()') THEN
+	   UNAME = ' '
+	ELSE IF (TRIM(UNAME).GT.0) THEN
+	   UNAME = ' ('//UNAME(:TRIM(UNAME))//')'
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE RECOUNT
+C
+C  SUBROUTINE RECOUNT
+C
+C  FUNCTION:
+C
+C  Fixes the message count of stored news groups.  This may become wrong
+C  if old copies of some of the database files are used with newer versions.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLFIL/ BULLFIL
+
+	COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+	CHARACTER*80 BULLNEWSDIR_FILE
+
+	FOLDER_NUMBER = 1000
+
+	FOLDER_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY)-1)//'.]'
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1)
+	END DO
+
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLNEWS
+	   RETURN
+	END IF
+
+	REMOTE_SET = 4
+
+	DO WHILE (IER.EQ.0)
+
+	   DO WHILE (REC_LOCK(IER))
+	      READ (7,IOSTAT=IER) NEWS_FOLDER_COM
+	   END DO
+
+	   IF (BTEST(NEWS_F_FLAG,8).AND.IER.EQ.0) THEN
+	      CALL NEWS_TO_FOLDER
+
+	      CALL OPEN_BULLDIR_SHARED
+
+	      NUM = F_START
+	      F_COUNT = 0
+
+	      IF (F_START.GT.0) THEN
+		 CALL READDIR(NUM,IER)
+		 NEXT = .TRUE.
+		 F_START = NUM
+		 DO WHILE (NUM+1.EQ.IER)
+		    F_COUNT = F_COUNT + 1
+		    NUM = NUM + 1
+		    IF (NUM.LE.F_NBULL) CALL READDIR(NUM,IER)
+		 END DO
+		 NEXT = .FALSE.
+
+		 F_NBULL = NUM - 1
+	      END IF
+
+	      CALL CLOSE_BULLDIR
+
+	      CALL REWRITE_FOLDER_FILE(IER)
+	   END IF
+	END DO
+
+	CALL DELLNM('BULL_NEWS_RECOUNT')
+
+	CALL CLOSE_BULLNEWS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELLNM(LOG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PSLDEF)'
+
+	CHARACTER*(*) LOG
+
+	CALL SYS$DELLNM('LNM$SYSTEM',LOG,PSL$C_SUPER)
+
+	RETURN
+	END
+
+
+	SUBROUTINE DELLNM_USER(LOG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PSLDEF)'
+
+	CHARACTER*(*) LOG
+
+	CALL SYS$DELLNM('LNM$PROCESS',LOG,PSL$C_USER)
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWNEWS(SINCE_BTIM,FOUND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /XHDR/ XHDR
+	LOGICAL XHDR /.FALSE./
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*8 NUMBER,NUMBER1
+
+	DIMENSION SINCE_BTIM(2)
+
+	START = F_START
+	END = F_NBULL
+
+	FOUND = 0
+
+	IF (REMOTE_SET.EQ.3.AND.XHDR) THEN
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.OTS$CVT_L_TI(END,NUMBER1,,,)) RETURN
+	   DO WHILE (NUMBER1(1:1).EQ.' ')
+	      NUMBER1 = NUMBER1(2:)
+	   END DO
+	   IF (.NOT.NEWS_WRITE('XHDR DATE '//NUMBER//'-'//NUMBER1))
+     &							     RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).EQ.'22') THEN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      DO WHILE (BUFFER(SB:EB).NE.'.')
+		 IF (FOUND.EQ.0) THEN
+		    L = INDEX(BUFFER(SB:EB),' ')
+		    CALL OTS$CVT_TI_L(BUFFER(SB:SB+L-2),IER,,%VAL(1))
+		    CALL NEWS_TIME(BUFFER(SB+L:EB),MSG_BTIM)
+		    CALL CONVERT_FROM_GMT(MSG_BTIM)
+		    IF (COMPARE_BTIM(SINCE_BTIM,MSG_BTIM).LT.0)
+     &			     FOUND = IER
+		 END IF
+		 IF (.NOT.NEWS_READ()) RETURN
+	      END DO
+	      IF (FOUND.NE.0) THEN
+		 IF (.NOT.OTS$CVT_L_TI(FOUND,NUMBER,,,)) RETURN
+		 IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+	      END IF
+	   END IF
+	ELSE IF (REMOTE_SET.EQ.3.AND..NOT.XHDR) THEN
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).NE.'22') THEN
+	      IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (.NOT.OTS$CVT_TI_L(BUFFER(SB+4:
+     &		  INDEX(BUFFER(SB+4:),' ')+SB+2),I,,%VAL(1))) RETURN
+	      IF (BUFFER(:2).NE.'22'.OR.I.LT.START) THEN
+		 BUFFER(:3) = '500'
+		 DO WHILE (START.LE.F_NBULL.AND.BUFFER(:2).NE.'22')
+		    START = START + 1
+		    IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+		 IF (BUFFER(:2).NE.'22') THEN
+		    IER = 0
+		    END = START - 1
+		    RETURN
+		 END IF
+	      END IF
+	      IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+	      END = START + NUMDIR - 1
+	   END IF
+	   IER = 0
+	   I = START
+	   DO WHILE (IER.EQ.0.AND.I.LE.END.AND.FOUND.EQ.0)
+	      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &		     INDEX(BUFFER(SB+4:),' ')+SB+2),MSG_NUM,,%VAL(1))
+	      CALL NEWS_HEADER(IER)
+	      IF (IER.NE.0) RETURN
+	      CALL CONVERT_FROM_GMT(MSG_BTIM)
+	      IF (COMPARE_BTIM(SINCE_BTIM,MSG_BTIM).LT.0) FOUND = MSG_NUM
+	      I = I + 1
+	      IF (REMOTE_SET.EQ.3.AND.I.LE.END.AND.FOUND.EQ.0) THEN
+		 IER = 2
+		 IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IF (BUFFER(:3).NE.'223') THEN
+		    END = I - 1
+		    IER = 0
+		    RETURN
+		 END IF
+		 IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IER = 0
+	      END IF
+	   END DO
+	   IF (FOUND.EQ.0) THEN
+	      IF (.NOT.OTS$CVT_L_TI(BULL_POINT,NUMBER,,,)) RETURN
+	      IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST_ALT(FOLDER1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /ALT_FOUND/ ALT_FOUND
+	CHARACTER*128 ALT_FOUND
+
+        CHARACTER*(*) FOLDER1
+
+	TEST_ALT = .FALSE.
+
+	OPEN (UNIT=3,FILE=FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &	      'BULL_ALT_NEWS.LIS',IOSTAT=IER,STATUS='OLD',READONLY)
+	
+	IF (IER.NE.0) RETURN
+
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(A)',IOSTAT=IER) ALT_FOUND
+	   IF (STREQ(ALT_FOUND(:INDEX(ALT_FOUND,':')-1),
+     &	      FOLDER1(:TRIM(FOLDER1)))) THEN
+	      ALT_FOUND = ALT_FOUND(INDEX(ALT_FOUND,':')+1:)
+	      CLOSE (UNIT=3)
+	      TEST_ALT = .TRUE.
+	      RETURN
+	   END IF
+	END DO
+
+	CLOSE (UNIT=3)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION SET_ALT(NEWALT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) NEWALT
+
+	COMMON /ALT/ ALT,SETALT
+	CHARACTER*64 ALT
+	LOGICAL SETALT
+	DATA SETALT/.FALSE./
+
+	SET_ALT = .FALSE.
+
+	IF (SETALT) THEN
+	   IF (NEWALT.EQ.ALT) THEN
+	      SET_ALT = .TRUE.
+	      RETURN
+	   ELSE
+	      CALL UNSET_ALT
+	   END IF
+	END IF
+
+	CALL NEWS_LOGOUT
+
+	CALL CRELNM('BULL_NEWS_SERVER',NEWALT(:TRIM(NEWALT)))
+
+	IF (NEWS_LOGIN()) THEN
+	   SET_ALT = .TRUE.
+	   SETALT = .TRUE.
+	   ALT = NEWALT
+	ELSE
+	   CALL DELLNM_USER('BULL_NEWS_SERVER')
+	   SETALT = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+        SUBROUTINE UNSET_ALT
+
+        IMPLICIT INTEGER (A-Z)
+
+        COMMON /ALT/ ALT,SETALT
+        CHARACTER*64 ALT
+	LOGICAL SETALT
+
+	CALL DELLNM_USER('BULL_NEWS_SERVER')
+
+	CALL NEWS_LOGOUT
+
+	SETALT = .FALSE.
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION ALT_SET()
+
+        COMMON /ALT/ ALT,SETALT
+        CHARACTER*64 ALT
+	LOGICAL SETALT
+
+	ALT_SET = SETALT
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_NEW_NEWS_ENTRY(FLEN,LOCAL_UPDATE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	DIMENSION EXPIRED(2)
+
+	CALL STR$UPCASE(NEWS_FOLDER,NEWS_FOLDER1)
+	IER2 = 1
+	I = FLEN
+	NEWS_F1_COUNT = NEWS_F_COUNT
+	DO WHILE (IER2.NE.0.AND.I.GT.1)
+	   IF (NEWS_FOLDER(I:I).EQ.'.') THEN
+	      NEWS_FOLDER = NEWS_FOLDER(:I)
+	      DO WHILE (REC_LOCK(IER))
+	         READ (7,KEY=NEWS_FOLDER,
+     &	               KEYID=0,IOSTAT=IER2) NEWS_FOLDER_COM
+	      END DO
+	   END IF
+	   IF (IER2.NE.0) I = I - 1
+	END DO
+	NEWS_F_COUNT = NEWS_F1_COUNT
+	IER = 0
+	DO WHILE (IER.EQ.0.AND.IER1.EQ.0)
+	   DO WHILE (REC_LOCK(IER))
+	      READ (7,KEY=NEWS_F_COUNT,KEYID=1,IOSTAT=IER)
+	   END DO
+	   IF (IER.EQ.0) NEWS_F_COUNT = NEWS_F_COUNT + 1
+	END DO
+	NEWS_FOLDER1_NUMBER = NEWS_F_COUNT
+	IF (IER2.EQ.0) THEN
+	   NEWS_F1_FLAG = NEWS_F_FLAG
+	   NEWS_F1_FLAG = IBCLR(NEWS_F1_FLAG,10)
+	   IF (I.NE.INDEX(NEWS_FOLDER1,'.')) THEN
+	      NEWS_F1_EXPIRE = NEWS_F_EXPIRE
+	      NEWS_F1_EXPIRE_LIMIT = NEWS_F_EXPIRE_LIMIT
+	   END IF
+	ELSE
+	   NEWS_F1_FLAG = NEWS_FLAG_DEFAULT
+	   NEWS_F1_EXPIRE = 0
+	   NEWS_F1_EXPIRE_LIMIT = 0
+	END IF
+	CALL GET_MSGKEY(NEWS_F1_NEWEST_BTIM,NEWS_F1_CREATED_DATE)
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',EXPIRED)
+	CALL GET_MSGKEY(EXPIRED,NEWS_F1_EXPIRED_DATE)
+	NEWS_F1_COUNT = MAX(0,NEWS_F1_NBULL - NEWS_F1_START + 1)
+	IF (BTEST(NEWS_F1_FLAG,8)) THEN
+	   NEWS_F1_COUNT = 0
+	   NEWS_F1_START = 0
+	   NEWS_F1_NBULL = 0
+	   NEWS_F1_FIRST = 0
+	   NEWS_F1_LAST = 0
+	END IF
+
+	WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	IF (IER.EQ.0) THEN
+	  NEWS_F_COUNT = NEWS_F_COUNT + 1
+	   IF (BTEST(NEWS_F1_FLAG,8).AND.
+     &	     .NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+	       CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,
+     &	     	%DESCR(NEWS_FOLDER1_NUMBER))
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE UPDATE_NEWS_ENTRY(SPECIAL,LOCAL_UPDATE,FLEN,SP)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	IF (BTEST(NEWS_F1_FLAG,8).AND.
+     &			.NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+	   IF (NEWS_F1_LAST.NE.NEWS_F1_NBULL.AND..NOT.SPECIAL.AND.
+     &	       NEWS_F1_START.LE.NEWS_F1_NBULL) THEN
+	      IF (NEWS_F1_FIRST.GT.NEWS_F1_START.AND.
+     &		  NEWS_F1_FIRST.GT.NEWS_F1_NBULL) THEN
+		 NEWS_F1_LAST = 0
+		 NEWS_F1_START = F1_START
+		 NEWS_F1_NBULL = F1_NBULL
+		 REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	      END IF
+	      IF (NEWS_F1_LAST.LT.NEWS_F1_NBULL) THEN
+		 CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,
+     &					%DESCR(NEWS_FOLDER1_NUMBER))
+	      END IF
+	   END IF
+	ELSE IF (.NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+	   UPDATE = .FALSE.
+	   IF (SP.GT.0) THEN 
+	      IF (FLEN.GT.44) THEN
+	         IF (NEWS_FOLDER1_DESCRIP.NE.
+     &	             BUFFER(SB+44:FLEN+SB-1)//BUFFER(SP:EB)) THEN
+		    NEWS_FOLDER1_DESCRIP =
+     &			BUFFER(SB+44:FLEN+SB-1)//BUFFER(SP:EB)
+		    UPDATE = .TRUE.
+	         END IF
+	      ELSE IF (NEWS_FOLDER1_DESCRIP.NE.BUFFER(SP:EB)) THEN
+	         NEWS_FOLDER1_DESCRIP = BUFFER(SP:EB)
+	         UPDATE = .TRUE.
+	      END IF
+	   ELSE
+	      UPDATE = .TRUE.
+	   END IF
+	   IF (SPECIAL) THEN
+	      IF (UPDATE) THEN
+		 NEWS_F1_START = F1_START
+		 NEWS_F1_NBULL = F1_NBULL
+	      END IF
+	   ELSE IF (.NOT.UPDATE) THEN
+	      UPDATE = F1_START.LT.NEWS_F1_START.OR.
+     &		       F1_NBULL.NE.NEWS_F1_NBULL
+	   END IF
+	   IF (UPDATE) REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin11.for b/decus/vmslt00a/bulletin/bulletin11.for
new file mode 100755
index 0000000000000000000000000000000000000000..77a03ee99d14f8176a652d6c1da014f5fa1f877f
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin11.for
@@ -0,0 +1,3599 @@
+C
+C  BULLETIN11.FOR, Version 10/6/98
+C  Purpose: Bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE RESET
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.GE.3) THEN
+	   IF (NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) THEN
+	      WRITE (6,'('' ERROR: NEWS group is not subscribed.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('CURRENT')) THEN
+	   MESSAGE_NUMBER = BULL_POINT
+	ELSE IF (.NOT.CLI$GET_VALUE('NUMBER',BULL_PARAMETER,LEN_P)) THEN
+	   MESSAGE_NUMBER = NBULL
+	ELSE
+	   CALL GET_2_VALS(BULL_PARAMETER,LEN_P,MESSAGE_NUMBER,EBULL,IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'(A)') 
+     &	        ' ERROR: Specified message number has incorrect format.'
+	      RETURN
+	   END IF
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(MESSAGE_NUMBER,IER)
+	IF (IER.EQ.MESSAGE_NUMBER+1		! Was message found?
+     &	          .OR.REMOTE_SET.GE.3) THEN	! Ignore if news
+	   IF (REMOTE_SET.LT.3) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+	   ELSE
+	      I = NEWS_FIND_SUBSCRIBE()
+	      LAST_NEWS_READ(2,I) = MESSAGE_NUMBER
+	      LAST_NEWS_READ2(2,I) = MIN(8191,F_NBULL-MESSAGE_NUMBER)
+     &			.OR.(LAST_NEWS_READ2(2,I).AND.'E000'X)
+	   END IF
+	ELSE
+	   WRITE(6,1030) MESSAGE_NUMBER
+	END IF
+
+100	IF (REMOTE_SET.GE.3) CALL READDIR(BULL_POINT,IER)
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+
+1010	FORMAT(' ERROR: You have not read any message.')
+1030	FORMAT(' ERROR: Message was not found: ',I)
+
+	END
+
+
+
+	SUBROUTINE TAG(ADD_OR_DEL,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+	DATA BULL_TAG /.FALSE./,READ_TAG /.FALSE./,BULL_NEWS_TAG /.FALSE./
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	CHARACTER*12 TAG_KEY
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	IF ((.NOT.BULL_TAG.AND.REMOTE_SET.LT.3)
+     &	    .OR.(.NOT.BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)) THEN
+	   CALL OPEN_NEW_TAG(IER)
+	   IF (.NOT.IER) RETURN
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+	   IF (NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) THEN
+	      WRITE (6,'('' ERROR: NEWS group is not subscribed.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	IF (ADD_OR_DEL.AND.
+     &		INCMD(:4).NE.'MARK'.AND.INCMD(:4).NE.'SEEN') THEN
+	   CALL ADD_TAG(IER,TAG_TYPE)
+	   RETURN
+	END IF
+
+	IF (INCMD(:4).EQ.'SEEN') THEN
+	   IF (CLI$PRESENT('READ').EQ.%LOC(CLI$_NEGATED)) THEN
+	      READ (13,KEYEQ=TAG_KEY(0,BULLDIR_HEADER,1),
+     &		    IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE (UNIT=13)
+	      BULL_TAG = IBCLR(BULL_TAG,1)
+	      RETURN
+	   END IF
+	END IF
+
+	IF (.NOT.CLI$PRESENT('NUMBER')) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! No.  Have we just read a bulletin?
+	      WRITE(6,1010)		! No, then error.
+	      RETURN
+	   ELSE IF (ADD_OR_DEL) THEN
+	      CALL ADD_TAG(IER,TAG_TYPE)
+	   ELSE
+	      CALL DEL_TAG(IER,TAG_TYPE)
+	      IF (IER.NE.0) THEN
+		 IF (TAG_TYPE.EQ.1) THEN
+		    WRITE (6,'('' ERROR: Message was not marked.'')')
+		 ELSE
+		    WRITE (6,'('' ERROR: Message was not seen.'')')
+		 END IF
+	      END IF
+	   END IF
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	LAST = 0
+
+	DO WHILE (CLI$GET_VALUE('NUMBER',BULL_PARAMETER,LEN_P)
+     &	    .NE.%LOC(CLI$_ABSENT)) 		! Get the specified messages
+
+	   CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+
+	   IF (SBULL.LE.0.OR.IER.NE.0.OR.SBULL.GT.F_NBULL) THEN
+	      WRITE (6,'(A)') 
+     &	        ' ERROR: Specified message number has incorrect format.'
+	      GO TO 100
+	   END IF
+
+	   DO MESSAGE_NUMBER = SBULL,MIN(EBULL,F_NBULL)
+
+	      CALL READDIR(MESSAGE_NUMBER,IER)
+	      IF (IER.NE.MESSAGE_NUMBER+1	! Was message found?
+     &	          .AND.REMOTE_SET.LT.3) THEN	! Ignore if news
+	         WRITE(6,1030) MESSAGE_NUMBER	! No
+		 GO TO 100
+	      ELSE IF (ADD_OR_DEL) THEN
+	         CALL ADD_TAG(IER,TAG_TYPE)
+	         IF (TAG_TYPE.EQ.2.AND.MESSAGE_NUMBER.GT.LAST) THEN
+		    IF (REMOTE_SET.LT.3) THEN
+	   	       DIFF = COMPARE_BTIM(MSG_BTIM,
+     &				LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+		       IF (DIFF.GT.0) CALL COPY2(LAST_READ_BTIM
+     &		          	(1,FOLDER_NUMBER+1),MSG_BTIM)
+		    ELSE
+		       CALL NEWS_UPDATE_NEWEST_MESSAGE(MESSAGE_NUMBER)
+	            END IF
+	            LAST = MESSAGE_NUMBER
+	         END IF
+	      ELSE
+	         CALL DEL_TAG(IER,TAG_TYPE)
+	      END IF
+	   END DO
+	END DO
+
+100	IF (REMOTE_SET.GE.3) CALL READDIR(BULL_POINT,IER)
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+
+1010	FORMAT(' ERROR: You have not read any message.')
+1030	FORMAT(' ERROR: Message was not found: ',I)
+
+	END
+
+
+
+	SUBROUTINE ADD_TAG(IER,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER*12 TAG_KEY
+
+	IF (REMOTE_SET.LT.3) THEN
+	   IF (TAG_TYPE.EQ.2.AND..NOT.BTEST(BULL_TAG,1)) THEN ! No SEEN tags
+	      WRITE (13,IOSTAT=IER) TAG_KEY(0,BULLDIR_HEADER,1)
+	      BULL_TAG = IBSET(BULL_TAG,1)
+	   END IF
+	   WRITE (13,IOSTAT=IER) TAG_KEY(FOLDER_NUMBER,MSG_KEY,TAG_TYPE)
+	ELSE
+	   CALL ADD_NEWS_TAG(IER,TAG_TYPE)
+	   RETURN
+	END IF
+
+	IF (IER.NE.FOR$IOS_INCKEYCHG.AND.IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Unable to mark message.'')')
+	   CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	ELSE
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_FIRST_NEWS_TAG(IER,MESSAGE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+        COMMON /NEXT/ NEXT
+
+	IER = 36
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	DO J=1,2
+	   IF (BTEST(READ_TAG,J)) I = J
+	END DO
+
+	IF (NEWS_TAG(3,I,SUBNUM).EQ.0) RETURN
+
+	INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	CLOSE_IT = .NOT.CLOSE_IT
+	IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+
+	OLD_NEXT = NEXT
+
+	NEXT = .FALSE.
+	J = F_START - 1
+	IER1 = J
+	DO WHILE (J.LE.F_NBULL.AND.J+1.NE.IER1)
+	   J = J + 1
+	   CALL READDIR(J,IER1)
+	END DO
+
+	IF (J+1.NE.IER1) THEN
+	   NEXT = OLD_NEXT
+	   IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+	   RETURN
+	END IF
+
+	NEXT = .TRUE.
+
+	DO MESSNUM = NEWS_TAG(1,I,SUBNUM),NEWS_TAG(2,I,SUBNUM)
+	   TEST = TEST_TAG(MESSNUM,%VAL(NEWS_TAG(3,I,SUBNUM)),
+     &			NEWS_TAG(1,I,SUBNUM))
+	   IF (BTEST(READ_TAG,3)) TEST = .NOT.TEST
+	   IF (TEST) THEN
+	      HEADER = .TRUE.
+	      CALL GET_NEXT_NEWS_TAG(IER,MESSNUM,HEADER,I,SUBNUM)
+	      IF (IER.EQ.0) MESSAGE = MESSNUM
+	      NEXT = OLD_NEXT
+	      IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+	      RETURN
+	   END IF
+	END DO
+
+	NEXT = OLD_NEXT
+	IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+
+	RETURN
+
+	ENTRY GET_THIS_NEWS_TAG(IER,MESSAGE,TAG_TYPE)
+
+	IER = 36
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	TAG_TYPE = 0
+
+	DO I=1,2
+	   IF ((BTEST(READ_TAG,I).OR.BTEST(READ_TAG,3))
+     &	    .AND.(NEWS_TAG(3,I,SUBNUM).GT.0).AND.
+     &	    (MSG_NUM.LE.NEWS_TAG(2,I,SUBNUM))) THEN
+	      TEST = TEST_TAG(MSG_NUM,
+     &		%VAL(NEWS_TAG(3,I,SUBNUM)),NEWS_TAG(1,I,SUBNUM))
+	      IF (TEST) THEN
+	         IER = 0
+	         TAG_TYPE = IBSET(TAG_TYPE,I)
+	      END IF
+	   END IF
+	END DO
+
+	IF (BTEST(READ_TAG,3)) THEN
+	   IF ((.NOT.BTEST(TAG_TYPE,2).OR..NOT.BTEST(READ_TAG,2)).AND.
+     &	       (.NOT.BTEST(TAG_TYPE,1).OR..NOT.BTEST(READ_TAG,1))) THEN
+	      IER = 0
+	   ELSE
+	      IER = 36
+	   END IF
+	END IF
+
+	RETURN
+
+	ENTRY GET_THIS_OR_NEXT_NEWS_TAG(NUM,IER,MESSAGE,TAG_TYPE)
+
+	IER = 36
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	HEADER = .FALSE.
+
+	TAG_TYPE = 0
+
+	DO WHILE (IER.NE.0)
+	   I = 0
+	   DO J=1,2
+	      IF (NEWS_TAG(3,J,SUBNUM).GT.0.AND.BTEST(READ_TAG,J)) THEN
+		 IER = 36
+		 MNUM = MAX(NEWS_TAG(1,J,SUBNUM),NUM)
+	   	 DO WHILE (IER.NE.0.AND.MNUM.LE.NEWS_TAG(2,J,SUBNUM))
+	     	    TEST = TEST_TAG(MNUM,%VAL(NEWS_TAG(3,J,SUBNUM)),
+     &		  	NEWS_TAG(1,J,SUBNUM))
+		    IF (BTEST(READ_TAG,3)) TEST = .NOT.TEST
+		    IF (TEST) THEN
+		       IER = 0
+		    ELSE
+		       MNUM = MNUM + 1
+		    END IF
+		 END DO
+		 IF (IER.EQ.0) THEN
+		    IF (J.EQ.1) THEN
+		       MESSAGE = MNUM
+		       I = 1
+		    ELSE IF (I.EQ.0.OR.MESSAGE.GT.MNUM) THEN
+		       MESSAGE = MNUM
+		       I = 2
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (I.EQ.0) RETURN
+	   CALL GET_NEXT_NEWS_TAG(IER,MESSAGE,HEADER,I,SUBNUM)
+	   IF (IER.EQ.0) THEN
+	      IF (.NOT.BTEST(READ_TAG,3)) TAG_TYPE = IBSET(TAG_TYPE,I)
+	      IF (NEWS_TAG(3,3-I,SUBNUM).GT.0.AND.
+     &		  MESSAGE.LE.NEWS_TAG(2,3-I,SUBNUM)) THEN
+		 IF (TEST_TAG(MESSAGE,%VAL(NEWS_TAG(3,3-I,SUBNUM)),
+     &		  	NEWS_TAG(1,3-I,SUBNUM))) THEN
+		    TAG_TYPE = IBSET(TAG_TYPE,3-I)
+                 END IF
+	      END IF
+	      RETURN
+	   ELSE IF (.NOT.BTEST(READ_TAG,3-I)) THEN
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NEXT_NEWS_TAG(IER,MESSNUM,HEADER,J,SUBNUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+        COMMON /NEXT/ NEXT
+
+	INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	CLOSE_IT = .NOT.CLOSE_IT
+	IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+
+	IER = 36
+
+	OLD_NEXT = NEXT
+
+	DO WHILE (MESSNUM.LE.NEWS_TAG(2,J,SUBNUM).AND.IER.NE.0)
+	   I = MAX(NEWS_TAG(1,J,SUBNUM),MESSNUM)
+	   DO WHILE (IER.NE.0.AND.I.LE.NEWS_TAG(2,J,SUBNUM))
+	      TEST = TEST_TAG(I,%VAL(NEWS_TAG(3,J,SUBNUM)),
+     &		  NEWS_TAG(1,J,SUBNUM))
+	      IF (BTEST(READ_TAG,3)) TEST = .NOT.TEST
+	      IF (TEST) THEN
+	         IER = 0
+	         MESSNUM = I
+	      ELSE
+		 I = I + 1
+	      END IF
+	   END DO
+	   IF (IER.EQ.0) THEN
+	      SAVE_MESSNUM = MESSNUM
+	      NEXT = .FALSE.
+	      CALL READDIR(MESSNUM,IER1)
+	      IF (IER1.NE.MESSNUM+1) THEN
+	         NEXT = .TRUE.
+	         CALL READDIR(MESSNUM,IER1)
+	      END IF
+	      IF (IER1.NE.MESSNUM+1) THEN
+		 IER = 36
+	         IF (.NOT.BTEST(READ_TAG,3)) THEN
+		    CALL DEL_NEWS_TAG(J,MESSNUM,SUBNUM)
+		 ELSE
+		    NEXT = OLD_NEXT
+		    IF (CLOSE_IT) CALL CLOSE_BULLDIR
+		    RETURN
+		 END IF
+		 IF (BTEST(READ_TAG,1).AND.BTEST(READ_TAG,2)) RETURN
+	      ELSE IF (MESSNUM.NE.SAVE_MESSNUM) THEN
+		 IER = 36
+	         IF (.NOT.BTEST(READ_TAG,3)) THEN
+		    CALL DEL_NEWS_TAG(J,SAVE_MESSNUM,SUBNUM)
+		 END IF
+	      END IF
+	   ELSE
+	      MESSNUM = NEWS_TAG(2,J,SUBNUM) + 1
+	   END IF
+	END DO
+
+	IF (IER.EQ.0.AND.HEADER) THEN
+	   MESSNUM = MESSNUM - 1
+	   MSG_NUM = MESSNUM
+	END IF
+
+	NEXT = OLD_NEXT
+
+	IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE ADD_NEWS_TAG(IER,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	IF (.NOT.BULL_NEWS_TAG) RETURN
+
+	IER = 0
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	IF (NEWS_TAG(1,TAG_TYPE,SUBNUM).GT.F_START) THEN
+	   CALL LIB$FREE_VM((NEWS_TAG(2,TAG_TYPE,SUBNUM)-
+     &			  NEWS_TAG(1,TAG_TYPE,SUBNUM))/8+1,
+     &			  NEWS_TAG(3,TAG_TYPE,SUBNUM))
+	   NEWS_TAG(2,TAG_TYPE,SUBNUM) = F_NBULL
+	   NEWS_TAG(3,TAG_TYPE,SUBNUM) = 0
+	END IF
+
+	IF (NEWS_TAG(3,TAG_TYPE,SUBNUM).EQ.0.AND.F_NBULL.GE.F_START) THEN
+	   NEWS_TAG(1,TAG_TYPE,SUBNUM) = F_START
+	   NEWS_TAG(2,TAG_TYPE,SUBNUM) = F_NBULL
+	   CALL LIB$GET_VM((F_NBULL-F_START)/8+1,
+     &			   NEWS_TAG(3,TAG_TYPE,SUBNUM))
+	   CALL ZERO_VM((F_NBULL-F_START)/8+1,
+     &			%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)))
+	ELSE IF (F_NBULL.GT.NEWS_TAG(2,TAG_TYPE,SUBNUM)) THEN
+	   DO I=1,2
+	      IF (NEWS_TAG(1,I,SUBNUM).GT.0) THEN
+	         CALL LIB$GET_VM((F_NBULL-NEWS_TAG(1,I,SUBNUM))/8+1,TEMP)
+	         CALL ZERO_VM((F_NBULL-NEWS_TAG(1,I,SUBNUM))/8+1,
+     &			%VAL(TEMP))
+	         CALL LIB$MOVC3((NEWS_TAG(2,I,SUBNUM)-
+     &			  NEWS_TAG(1,I,SUBNUM))/8+1,
+     &			  %VAL(NEWS_TAG(3,I,SUBNUM)),%VAL(TEMP))
+	         CALL LIB$FREE_VM((NEWS_TAG(2,I,SUBNUM)-
+     &			  NEWS_TAG(1,I,SUBNUM))/8+1,
+     &			  NEWS_TAG(3,I,SUBNUM))
+	         NEWS_TAG(2,I,SUBNUM) = F_NBULL
+	         NEWS_TAG(3,I,SUBNUM) = TEMP
+	      END IF
+	   END DO
+	END IF
+
+	CALL SET_TAG(MSG_NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		     NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	NEWS_TAG(4,TAG_TYPE,SUBNUM) = 1
+		 
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_TAG(NUM,TAGS,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION TAGS(1)
+
+	I = (NUM-START)/32
+	J = NUM - START - I*32
+
+	TAGS(I+1) = IBSET(TAGS(I+1),J)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CLR_TAG(NUM,TAGS,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION TAGS(1)
+
+	I = (NUM-START)/32
+	J = NUM - START - I*32
+
+	TAGS(I+1) = IBCLR(TAGS(I+1),J)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST_TAG(NUM,TAGS,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION TAGS(1)
+
+	I = (NUM-START)/32
+	J = NUM - START - I*32
+
+	TEST_TAG = BTEST(TAGS(I+1),J)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DEL_TAG(IER,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*12 TAG_KEY
+
+	IER = 0
+
+	IF (REMOTE_SET.GE.3) THEN
+	   SUBNUM = NEWS_FIND_SUBSCRIBE()
+	   CALL DEL_NEWS_TAG(TAG_TYPE,MSG_NUM,SUBNUM)
+	   RETURN
+	END IF
+
+	DO WHILE (REC_LOCK(IER1))
+	   READ (13,KEYEQ=TAG_KEY(FOLDER_NUMBER,MSG_KEY,TAG_TYPE),
+     &		 IOSTAT=IER1)
+	END DO
+	IF (IER1.NE.0) RETURN
+
+	DELETE (UNIT=13,IOSTAT=IER1)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DEL_NEWS_TAG(TAG_TYPE,MSG_NUM,SUBNUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	IF (MSG_NUM.LT.NEWS_TAG(1,TAG_TYPE,SUBNUM).OR.
+     &	   MSG_NUM.GT.NEWS_TAG(2,TAG_TYPE,SUBNUM).OR..NOT.TEST_TAG
+     &	    (MSG_NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM))
+     &	    ,NEWS_TAG(1,TAG_TYPE,SUBNUM))) THEN
+	   RETURN
+	ELSE
+	   NEWS_TAG(4,TAG_TYPE,SUBNUM) = 1
+	   CALL CLR_TAG
+     &		(MSG_NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE OPEN_OLD_TAG
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	CHARACTER*12 BULL_MARK_DIR
+	CHARACTER*12 TAG_KEY,INPUT_KEY
+
+	IER = SYS_TRNLNM('BULL_MARK',BULL_PARAMETER)
+	IF (IER) THEN
+	   BULL_MARK_DIR = 'BULL_MARK:'
+	ELSE
+	   BULL_MARK_DIR = 'SYS$LOGIN:'
+	END IF
+
+	NTRIES = 0
+
+	DO WHILE (FILE_LOCK(IER,IER1).AND.NTRIES.LE.30)
+	   OPEN (UNIT=13,FILE=BULL_MARK_DIR//
+     &	     USERNAME(:TRIM(USERNAME))//'.BULLMARK',STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	     ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	     KEY=(1:12:CHARACTER))
+	   NTRIES = NTRIES + 1
+	END DO
+
+	IF (IER.EQ.0) THEN
+	   BULL_TAG = IBSET(BULL_TAG,0)
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (13,KEY=TAG_KEY(0,BULLDIR_HEADER,1),IOSTAT=IER1)
+	   END DO
+	   IF (IER1.EQ.0) BULL_TAG = IBSET(BULL_TAG,1)
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (13,KEYGE=TAG_KEY('FFFF'X,BULLDIR_HEADER,1),IOSTAT=IER1)
+     &		         INPUT_KEY
+	   END DO
+	   CALL LIB$MOVC3(4,%REF(INPUT_KEY),FOLDER1_NUMBER)
+	   IF (IER1.EQ.0.AND.FOLDER1_NUMBER.EQ.'FFFF'X) THEN
+	      MSG_KEY = INPUT_KEY(5:)
+	      CALL SYS$ASCTIM(,DATE,MSG_BTIM,)
+	      IF (COMPARE_DATE(DATE,' ').LT.-30) THEN
+		 DELETE (13)
+	         IER1 = 2
+	      END IF
+	   END IF
+	   IF (IER1.NE.0.OR.FOLDER1_NUMBER.NE.'FFFF'X) THEN
+	      CLOSE (UNIT=13)           
+	      IER1 = 1
+              DO WHILE (IER1)
+	         IER1 = LIB$DELETE_FILE(
+     &			BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))
+     &	            	//'.BULLMARK;-1')
+	      END DO
+	      CALL CONV$PASS_FILES(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK',
+     &	        BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARKTMP')
+	      CALL CONV$PASS_OPTIONS()
+	      CALL CONV$CONVERT()
+	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK;1')
+    	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARKTMP',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK')
+              CALL LIB$DELETE_FILE(BULL_MARK_DIR//
+     &		USERNAME(:TRIM(USERNAME))//'.BULLMARK;-1')
+	      DO WHILE (FILE_LOCK(IER,IER1).AND.NTRIES.LE.30)
+	         OPEN (UNIT=13,FILE=BULL_MARK_DIR//
+     &	    	    USERNAME(:TRIM(USERNAME))//'.BULLMARK',STATUS='OLD',
+     &	    	    ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	    	    ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	    	    KEY=(1:12:CHARACTER))
+	  	 NTRIES = NTRIES + 1
+	      END DO
+	      CALL SYS_BINTIM('-',MSG_BTIM)
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      WRITE (13,IOSTAT=IER) TAG_KEY('FFFF'X,MSG_KEY,1)
+	   ELSE
+	      UNLOCK 13
+	   END IF
+	END IF
+
+	IF (IER.EQ.0.OR.IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	   OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	      USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	      ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	      FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	      KEY=(1:4:INTEGER))
+
+	   IF (IER.EQ.0) THEN
+	      IF (BULL_NEWS_TAG) RETURN
+	      BULL_NEWS_TAG = .TRUE.
+	   ELSE
+	      CALL ERRSNS(IDUMMY,IER1)
+	      IF (IER1.EQ.RMS$_FLK) THEN
+	         BULL_NEWS_TAG = .FALSE.
+	         RETURN
+	      END IF
+	   END IF
+
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (23,KEYEQ=0,IOSTAT=IER1) NEWS_MARK
+	   END DO
+	   IF (IER1.EQ.0) CALL SYS$ASCTIM(,DATE,NEWS_MARK(2),)
+	   IF (IER1.NE.0) THEN
+	      CLOSE (UNIT=23)
+	      OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:4:INTEGER))
+	      IF (IER.EQ.0) THEN
+	      OPEN (UNIT=24,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=128,DISPOSE='DELETE',
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:4:INTEGER))
+	      DO WHILE (IER.EQ.0)
+	         DO WHILE (REC_LOCK(IER))
+		    READ (23,IOSTAT=IER) NEWS_MARK
+	         END DO
+	         IF (IER.EQ.0) THEN
+		    I = NEWS_MARK2(1)
+		    NEWS_MARK2(1) = NEWS_MARK2(2)
+		    NEWS_MARK2(2) = I
+	            WRITE (24,IOSTAT=IER) NEWS_MARK
+	         END IF
+	      END DO
+	      NEWS_MARK(1) = 0
+	      CALL SYS_BINTIM('-',NEWS_MARK(2))
+	      WRITE (24,IOSTAT=IER) NEWS_MARK
+	      CLOSE (UNIT=24,DISPOSE='SAVE')
+	      CLOSE (UNIT=23,DISPOSE='DELETE')
+	      END IF
+	      DO WHILE (FILE_LOCK(IER,IER1))
+	        OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	           USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	           ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	           FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	           KEY=(1:4:INTEGER))
+	      END DO
+	   ELSE IF (COMPARE_DATE(DATE,' ').LT.-30) THEN
+	      CLOSE (UNIT=23)           
+	      IER1 = 1
+              DO WHILE (IER1)
+	         IER1 = LIB$DELETE_FILE(
+     &			BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))
+     &	            	//'.NEWSMARK;-1')
+	      END DO
+	      CALL CONV$PASS_FILES(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK',
+     &	        BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARKTMP')
+	      CALL CONV$PASS_OPTIONS()
+	      CALL CONV$CONVERT()
+	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK;1')
+	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARKTMP',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK')
+              CALL LIB$DELETE_FILE(BULL_MARK_DIR//
+     &		USERNAME(:TRIM(USERNAME))//'.NEWSMARK;-1')
+	      DO WHILE (FILE_LOCK(IER,IER1))
+	        OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	           USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	           ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	           FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	           KEY=(1:4:INTEGER))
+	      END DO
+	      DO WHILE (REC_LOCK(IER1))
+	         READ (23,KEYEQ=0,IOSTAT=IER1) NEWS_MARK
+	      END DO
+	      CALL SYS_BINTIM('-',NEWS_MARK(2))
+	      REWRITE (23,IOSTAT=IER) NEWS_MARK
+	   END IF
+	END IF
+
+	IF (IER.NE.0.AND.IER.NE.FOR$IOS_FILNOTFOU) THEN
+	   WRITE (6,'('' Unable to open mark file.'')')
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	   RETURN
+	END IF
+
+	IF (BULL_NEWS_TAG) THEN
+	   OLD_NEWS_NUMBER = 0
+	   NEWS_MARK(1) = 0
+	   FOLDER_NUMBER_SAVE = NEWS_FOLDER_NUMBER
+	   CALL OPEN_BULLNEWS_SHARED
+	   DO WHILE (IER.EQ.0)
+	      DO WHILE (REC_LOCK(IER))
+		 READ (23,KEYGT=NEWS_MARK(1),IOSTAT=IER) NEWS_MARK
+	      END DO
+	      IF (IER.EQ.0.AND.NEWS_NUMBER.NE.0) THEN
+		 IF (NEWS_NUMBER.NE.OLD_NEWS_NUMBER) THEN
+		    NEWS_FOLDER_NUMBER = NEWS_NUMBER
+		    SUBNUM = NEWS_FIND_SUBSCRIBE()
+		    IF (SUBNUM.GT.FOLDER_MAX-1) THEN
+		       DELETE (UNIT=23)
+		    ELSE
+		       OLD_NEWS_NUMBER = NEWS_NUMBER
+		       CALL READ_FOLDER_FILE_KEYNUM_TEMP
+     &			  (NEWS_FOLDER_NUMBER,IER1)
+		       IF (IER1.NE.0) THEN
+	      		  CALL ERRSNS(IDUMMY,IER2)
+		          IF (IER2.NE.RMS$_RNF) SUBNUM = 0
+		       ELSE
+			  DO I=1,2
+		             NEWS_TAG(1,I,SUBNUM) = F1_START
+		             NEWS_TAG(2,I,SUBNUM) = F1_NBULL
+		             NEWS_TAG(4,I,SUBNUM) = 0
+		             CALL LIB$GET_VM((F1_NBULL-F1_START)/8+1,
+     &					  NEWS_TAG(3,I,SUBNUM))
+		             CALL ZERO_VM((F1_NBULL-F1_START)/8+1,
+     &					%VAL(NEWS_TAG(3,I,SUBNUM)))
+			  END DO
+		       END IF
+		    END IF
+		 END IF
+		 IF (NEWS_NUMBER.EQ.OLD_NEWS_NUMBER) THEN
+	            IF (SUBNUM.EQ.0) THEN
+		       DELETE (UNIT=23)
+		    ELSE
+		       UNLOCK 23
+		       IF (NEWS_REC.GT.0) THEN
+			  TAG_TYPE = 1
+		       ELSE
+			  TAG_TYPE = 2
+		       END IF
+		       IF (NEWS_FORMAT.EQ.0) THEN	! 16 bit numbers
+		          DO I=5,256
+		             CALL SET_NEWS_TAG(INT(NEWS_MARK2(I)),SUBNUM,
+     &					   TAG_TYPE)
+		          END DO
+		       ELSE
+		          DO I=3,128
+		             CALL SET_NEWS_TAG(NEWS_MARK(I),SUBNUM,TAG_TYPE)
+		          END DO
+		       END IF
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   NEWS_FOLDER_NUMBER = FOLDER_NUMBER_SAVE
+	   CALL CLOSE_BULLNEWS
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_NEWS_TAG(NUM,SUBNUM,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	IF (NUM.GT.0) THEN
+	   LAST_NUM = NUM
+	   IF (NUM.LT.NEWS_TAG(1,TAG_TYPE,SUBNUM).OR.
+     &	       NUM.GT.NEWS_TAG(2,TAG_TYPE,SUBNUM)) RETURN
+	   CALL SET_TAG(NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	ELSE IF (NUM.LT.0) THEN
+	   IF (-NUM.LT.NEWS_TAG(1,TAG_TYPE,SUBNUM)) RETURN
+	   DO J=MAX(NEWS_TAG(1,TAG_TYPE,SUBNUM),LAST_NUM+1),
+     &		MIN(NEWS_TAG(2,TAG_TYPE,SUBNUM),-NUM)
+	      CALL SET_TAG(J,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE OPEN_NEW_TAG(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+
+	CHARACTER*12 BULL_MARK_DIR
+
+	DIMENSION BTIM(2)
+	CHARACTER KEY*8
+
+	IER = SYS_TRNLNM('BULL_MARK',BULL_PARAMETER)
+	IF (IER) THEN
+	   BULL_MARK_DIR = 'BULL_MARK:'
+	ELSE
+	   BULL_MARK_DIR = 'SYS$LOGIN:'
+	END IF
+
+	IER1 = SYS_TRNLNM_SYSTEM('BULL_MARK',BULL_PARAMETER)
+	IF (.NOT.IER1) THEN
+	   IER = SYS_TRNLNM('BULL_MARK',BULL_PARAMETER)
+	   CALL DISABLE_PRIVS
+	   IER1 = .FALSE.
+	END IF
+	IF (REMOTE_SET.LT.3) THEN
+	   MARKUNIT = 13
+	   OPEN (UNIT=MARKUNIT,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.BULLMARK',STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	        RECORDSIZE=3,
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:12:CHARACTER))
+	   IF (IER.EQ.0) THEN
+	      CALL SYS_BINTIM('-',BTIM)
+	      CALL GET_MSGKEY(BTIM,KEY)
+	      WRITE (13) TAG_KEY('FFFF'X,KEY,0)
+	   END IF
+	ELSE
+	   MARKUNIT = 23
+	   OPEN (UNIT=MARKUNIT,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	        RECORDSIZE=128,
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:4:INTEGER))
+	   IF (IER.EQ.0) THEN
+	      NEWS_MARK(1) = 0
+	      CALL SYS_BINTIM('-',NEWS_MARK(2))
+	      WRITE (23,IOSTAT=IER) NEWS_MARK
+           END IF
+ 	END IF
+	IF (.NOT.IER1) CALL ENABLE_PRIVS
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' Cannot create mark file.'')')
+	   CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	      IER = 0
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	      IER = IER1
+	   END IF
+	ELSE
+	   IF (.NOT.IER1) THEN
+	      INQUIRE (UNIT=MARKUNIT,NAME=BULL_PARAMETER)
+	      WRITE (6,'('' Created MARK file: '',A)')
+     &		BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+	   END IF
+	   IF (MARKUNIT.EQ.13) BULL_TAG = 1
+	   IF (MARKUNIT.EQ.23) BULL_NEWS_TAG = .TRUE.
+	   IER = 1
+	END IF
+
+	RETURN
+	END
+
+
+
+	CHARACTER*12 FUNCTION TAG_KEY(FOLDER_NUMBER,MSG_KEY,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) MSG_KEY
+
+	IF (TAG_TYPE.EQ.1) THEN
+	   CALL LIB$MOVC3(4,FOLDER_NUMBER,%REF(TAG_KEY))
+	ELSE
+	   CALL LIB$MOVC3(4,-(1+FOLDER_NUMBER),%REF(TAG_KEY))
+	END IF
+
+	CALL GET_MSGKEY(%REF(MSG_KEY),TAG_KEY(5:))
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_FIRST_TAG(FOLDER_NUMBER,IER,MESSAGE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*12 TAG_KEY,INPUT_KEY
+
+	CHARACTER*8 NEXT_MSG_KEY
+
+	IF ((.NOT.BULL_TAG.AND.REMOTE_SET.LT.3)
+     &	    .OR.(.NOT.BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)) THEN
+	   CALL OPEN_NEW_TAG(IER)
+	   IF (.NOT.IER) RETURN
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+	   CALL GET_FIRST_NEWS_TAG(IER,MESSAGE)
+	   RETURN
+	END IF
+
+	IF (BTEST(READ_TAG,3)) THEN
+	   MSG_NUM = 0
+ 	   CALL GET_NEXT_UNTAG(FOLDER_NUMBER,IER,MESSAGE,DUMMY)
+	   IF (IER.EQ.0) THEN
+	      MESSAGE = MESSAGE - 1
+	      MSG_NUM = MESSAGE
+	      MSG_KEY = BULLDIR_HEADER
+	   END IF
+	   RETURN
+	END IF
+
+	MSG_KEY = BULLDIR_HEADER
+
+	HEADER = .TRUE.
+
+	DO J=1,2
+	   IF (BTEST(READ_TAG,J)) I = J
+	END DO
+
+	CALL CONFIRM_TAG(IER,FOLDER_NUMBER,MESSAGE,HEADER,I)
+
+	RETURN
+
+	ENTRY GET_THIS_TAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+
+	IF (REMOTE_SET.GE.3) THEN
+	   CALL GET_THIS_NEWS_TAG(IER,MESSAGE,TAG_TYPE)
+	   RETURN
+	END IF
+
+	TAG_TYPE = 0
+
+	DO I=1,2
+	   IF (BTEST(READ_TAG,I).OR.BTEST(READ_TAG,3)) THEN
+	      DO WHILE (REC_LOCK(IER))
+	         READ (13,KEY=TAG_KEY(FOLDER_NUMBER,MSG_KEY,I),
+     &		   IOSTAT=IER) INPUT_KEY
+	      END DO
+	      IF (IER.EQ.0) TAG_TYPE = IBSET(TAG_TYPE,I)
+	   END IF
+	END DO
+
+	IF ((TAG_TYPE.NE.0.AND..NOT.BTEST(READ_TAG,3)).OR.
+     &	    (BTEST(READ_TAG,3).AND.
+     &	     (.NOT.BTEST(TAG_TYPE,2).OR..NOT.BTEST(READ_TAG,2)).AND.
+     &	     (.NOT.BTEST(TAG_TYPE,1).OR..NOT.BTEST(READ_TAG,1)))) THEN
+	   IF (IER.EQ.0) UNLOCK 13
+	   IER = 0
+	   MESSAGE = MSG_NUM
+	ELSE
+	   IER = 36
+	END IF
+
+	RETURN
+
+	ENTRY GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+
+	MSG_NUM = MSG_NUM - 1
+
+	CALL DECREMENT_MSG_KEY
+
+	ENTRY GET_NEXT_TAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+
+	IF (REMOTE_SET.GE.3) THEN
+	   MSG_NUM = ABS(MSG_NUM) + 1
+	   CALL GET_THIS_OR_NEXT_NEWS_TAG(MSG_NUM,IER,MESSAGE,TAG_TYPE)
+	   RETURN
+	END IF
+
+	IER = 36
+
+	HEADER = .FALSE.
+
+	TAG_TYPE = 0
+
+	IF (BTEST(READ_TAG,3)) THEN
+	   CALL GET_NEXT_UNTAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+	   RETURN
+	END IF
+
+	DO WHILE (IER.NE.0)
+	   I = 0
+	   DO J=1,2
+	      IF (BTEST(READ_TAG,J)) THEN
+	         DO WHILE (REC_LOCK(IER))
+	            READ (13,KEYGT=TAG_KEY(FOLDER_NUMBER,MSG_KEY,J),
+     &		        IOSTAT=IER) INPUT_KEY
+		 END DO
+		 IF (IER.EQ.0) THEN
+	            CALL LIB$MOVC3(4,%REF(INPUT_KEY),FOLDER1_NUMBER)
+		    IF ((J.EQ.1.AND.FOLDER1_NUMBER.NE.FOLDER_NUMBER).OR.
+     &		      (J.EQ.2.AND.FOLDER1_NUMBER.NE.-(1+FOLDER_NUMBER)))
+     &		      IER = 36
+		 END IF
+		 IF (IER.EQ.0) THEN
+		    IF (J.EQ.1) THEN
+		       NEXT_MSG_KEY = INPUT_KEY(5:)
+		       I = 1
+		    ELSE IF (I.EQ.0.OR.COMPARE_MSG_KEY(NEXT_MSG_KEY,
+     &			     INPUT_KEY(5:)).GT.0) THEN
+		       I = 2
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (I.EQ.0) RETURN
+	   NEXT_MSG_KEY = MSG_KEY
+	   CALL CONFIRM_TAG(IER,FOLDER_NUMBER,MESSAGE,HEADER,I)
+	   IF (IER.EQ.0) THEN
+	      TAG_TYPE = IBSET(TAG_TYPE,I)
+	      DO WHILE (REC_LOCK(IER))
+	         READ (13,KEY=TAG_KEY(FOLDER_NUMBER,MSG_KEY,3-I),
+     &		        IOSTAT=IER) INPUT_KEY
+	      END DO
+	      IF (IER.EQ.0) TAG_TYPE = IBSET(TAG_TYPE,3-I)
+	      IER = 0
+	      RETURN
+	   ELSE IF (.NOT.BTEST(READ_TAG,3-I)) THEN
+	      MSG_KEY = NEXT_MSG_KEY
+	      RETURN
+	   ELSE
+	      MSG_KEY = NEXT_MSG_KEY
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_NEXT_UNTAG(FN,IER,MESSAGE,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	CLOSE_IT = .NOT.CLOSE_IT
+	IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+
+	DO MESSAGE = MSG_NUM+1,F_NBULL
+	   CALL READDIR(MESSAGE,IER)
+	   IF (IER.EQ.MESSAGE+1) THEN
+	      CALL GET_THIS_TAG(FN,IER,DUMMY,TAG_TYPE)
+	      IF (IER.EQ.0) THEN
+		 IER = 0
+		 IF (CLOSE_IT) CALL CLOSE_BULLDIR
+		 RETURN
+	      END IF
+	   END IF
+	END DO
+
+	IER = 36
+	IF (CLOSE_IT) CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION COMPARE_MSG_KEY(MSG_KEY1,MSG_KEY2)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*8 MSG_KEY1,MSG_KEY2
+
+	DIMENSION BTIM1(2),BTIM2(2)
+
+	CALL GET_MSGBTIM(MSG_KEY1,BTIM1)
+	CALL GET_MSGBTIM(MSG_KEY2,BTIM2)
+
+	COMPARE_MSG_KEY = COMPARE_BTIM(BTIM1,BTIM2)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CONFIRM_TAG(IER,FOLDER_NUMBER,MESSAGE,HEADER,J)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER*12 TAG_KEY,INPUT_KEY
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (13,KEYGT=TAG_KEY(FOLDER_NUMBER,MSG_KEY,J),IOSTAT=IER)
+     &					INPUT_KEY
+	END DO
+
+	CLOSE_IT = .FALSE.
+
+	DO WHILE (FOLDER_NUMBER.GT.0)
+	   IF (IER.EQ.0) THEN
+	      CALL GET_MSGKEY(%REF(INPUT_KEY(5:)),MSG_KEY)
+	      CALL LIB$MOVC3(4,%REF(INPUT_KEY),FOLDER1_NUMBER)
+	   END IF
+
+	   IF (IER.EQ.0) THEN
+	      IF ((J.EQ.1.AND.FOLDER1_NUMBER.NE.FOLDER_NUMBER).OR.
+     &		  (J.EQ.2.AND.FOLDER1_NUMBER.NE.-(1+FOLDER_NUMBER)))
+     &		  IER = 36
+	   END IF
+	   IF (IER.NE.0) THEN
+	      IER = 1
+	      UNLOCK 13
+	      IF (CLOSE_IT) CALL CLOSE_BULLDIR
+	      RETURN
+	   ELSE
+	      CALL DECREMENT_MSG_KEY
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      INQUIRE (UNIT=2,OPENED=IER)
+	      IF (.NOT.IER) THEN
+		 CALL OPEN_BULLDIR_SHARED
+		 CLOSE_IT = .TRUE.
+	      END IF
+	      CALL READDIR_KEYGE(IER)
+	      CALL GET_MSGKEY(%REF(INPUT_KEY(5:)),INPUT_KEY(5:))
+	      IF (IER.NE.0.AND.MSG_KEY.EQ.INPUT_KEY(5:)) THEN
+	         UNLOCK 13
+		 MESSAGE = MSG_NUM
+		 IF (HEADER) THEN
+		    MESSAGE = MESSAGE - 1
+		    MSG_NUM = MESSAGE
+		    MSG_KEY = BULLDIR_HEADER
+		 END IF
+		 IER = 0
+		 IF (CLOSE_IT) CALL CLOSE_BULLDIR
+	         RETURN
+	      ELSE
+		 DELETE (UNIT=13)
+		 IF (BTEST(READ_TAG,1).AND.BTEST(READ_TAG,2)) THEN
+		    IER = 36
+		    IF (CLOSE_IT) CALL CLOSE_BULLDIR
+		    RETURN
+		 END IF
+		 DO WHILE (REC_LOCK(IER))
+	            READ (13,IOSTAT=IER) INPUT_KEY
+	 	 END DO
+	      END IF
+	   END IF
+
+	END DO
+
+	END
+
+
+
+	SUBROUTINE CLOSE_TAG
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	TAG_OPENED = .FALSE.
+
+	IF (BULL_NEWS_TAG) THEN
+	   DO I=1,FOLDER_MAX-1
+	      DO M=1,2
+	         IF (NEWS_TAG(3,M,I).NE.0.AND.NEWS_TAG(4,M,I).EQ.1) THEN
+	            IF (.NOT.TAG_OPENED) THEN
+		       CALL OPEN_OLD_TAG
+		       TAG_OPENED = .TRUE.
+		    END IF
+		    IF (M.EQ.1) THEN
+		       NEWS_REC = 1
+		    ELSE
+		       NEWS_REC = -32767
+		    END IF
+	            NEWS_FORMAT = 0
+		    IF (NEWS_TAG(2,M,I).GT.32767) NEWS_FORMAT = 1
+		    LIMIT = 256/(NEWS_FORMAT+1)
+	            NEWS_NUMBER = LAST_NEWS_READ2(1,I)
+		    K = 5-NEWS_FORMAT*2
+		    SET_LIST = .FALSE.
+		    DO J=NEWS_TAG(1,M,I),NEWS_TAG(2,M,I)
+		       IF (TEST_TAG(J,%VAL(NEWS_TAG(3,M,I)),
+     &				      NEWS_TAG(1,M,I))) THEN
+		          IF (.NOT.SET_LIST) THEN
+		             CALL SET_NEWS_MARK(K,J)
+			     LAST_SET = J
+			     K = K + 1
+		             SET_LIST = .TRUE.
+		          END IF
+		       ELSE IF (SET_LIST) THEN
+		          IF (LAST_SET.NE.J-1) THEN
+			     CALL SET_NEWS_MARK(K,-(J-1))
+		             K = K + 1
+			  END IF
+		          SET_LIST = .FALSE.
+		       END IF
+		       IF (J.EQ.NEWS_TAG(2,M,I)) THEN
+		          IF (SET_LIST.AND.LAST_SET.NE.J) THEN
+			     CALL SET_NEWS_MARK(K,-J)
+		             K = K + 1
+		          END IF
+		          DO L=K,LIMIT
+			     CALL SET_NEWS_MARK(L,0)
+		          END DO
+		          K = LIMIT + 1
+		       END IF
+		       IF (K.GT.LIMIT) THEN
+		          DO WHILE (REC_LOCK(IER))
+		             READ (23,KEYEQ=NEWS_MARK(1),IOSTAT=IER)
+		          END DO
+		          IF (IER.NE.0) THEN
+		             WRITE (23,IOSTAT=IER) NEWS_MARK
+		          ELSE
+		             REWRITE (23,IOSTAT=IER) NEWS_MARK
+		          END IF
+		          K = 5-NEWS_FORMAT*2
+		          NEWS_REC = NEWS_REC + 1
+		          IF (J.EQ.NEWS_TAG(2,M,I)) THEN
+		             DO WHILE (REC_LOCK(IER))
+		                READ (23,KEYEQ=NEWS_MARK(1),IOSTAT=IER)
+			        IF (IER.EQ.0) THEN
+			           DELETE (UNIT=23)
+				   NEWS_REC = NEWS_REC + 1
+				   L = REC_LOCK(IER)
+			        END IF
+			     END DO
+		          END IF
+		       END IF
+		    END DO
+	         END IF
+	      END DO
+	   END DO
+	   CLOSE (UNIT=23)
+	END IF
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET_NEWS_MARK(I,J)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	IF (NEWS_FORMAT.EQ.0) THEN
+	   NEWS_MARK2(I) = J
+	ELSE
+	   NEWS_MARK(I) = J
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ZERO_VM(NUM,NEWS_TAG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	LOGICAL*1 NEWS_TAG(1)
+
+	DO I=1,NUM
+	   NEWS_TAG(I) = 0
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FREE_TAGS(ISUB)
+
+        IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	DO I=1,2
+	   IF (NEWS_TAG(3,I,ISUB).GT.0) THEN
+	      CALL LIB$FREE_VM(
+     &		(NEWS_TAG(2,I,ISUB)-NEWS_TAG(1,I,ISUB))/8+1,NEWS_TAG(3,I,ISUB))
+	      NEWS_TAG(3,I,ISUB) = 0
+	      NEWS_NUMBER = NEWS_FOLDER_NUMBER
+	      NEWS_REC = -32768
+	      DO WHILE (REC_LOCK(IER))
+	         READ (23,KEYGT=NEWS_MARK(1),IOSTAT=IER) NEWS_MARK
+	         IF (IER.EQ.0.AND.NEWS_NUMBER.EQ.NEWS_FOLDER_NUMBER) THEN
+		    DELETE (UNIT=23)
+		    L = REC_LOCK(IER)
+	         END IF
+	      END DO
+	      IF (IER.EQ.0) UNLOCK 23
+	   END IF
+
+	   DO J=I,FOLDER_MAX-2
+	      CALL LIB$MOVC3(16,NEWS_TAG(1,I,J+1),NEWS_TAG(1,I,J))
+	   END DO
+
+	   DO J=1,4
+	      NEWS_TAG(J,I,FOLDER_MAX-1) = 0
+	   END DO
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_PREVIOUS_TAG(FN,IER,BULL_READ,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER*8 PREV_MSG_KEY
+
+	IER = 36
+
+	IF (REMOTE_SET.GE.3) THEN
+	   INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	   CLOSE_IT = .NOT.CLOSE_IT
+	   IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+	   SUBNUM = NEWS_FIND_SUBSCRIBE()
+	   DO WHILE (IER.NE.0.AND.MSG_NUM.GT.F_START)
+	      MSG_NUM = MSG_NUM - 1
+	      CALL GET_THIS_TAG(FN,IER,MSG_NUM,TAG_TYPE)
+	      IF (IER.EQ.0) THEN
+		 TMP_MSG_NUM = MSG_NUM
+	         CALL READDIR(TMP_MSG_NUM,IER1)
+	         IF (IER1.NE.MSG_NUM+1) THEN
+	            IF (.NOT.BTEST(READ_TAG,3)) THEN
+		       CALL DEL_NEWS_TAG(TAG_TYPE,TMP_MSG_NUM,SUBNUM)
+		    END IF
+		    IER = 36
+	         END IF
+	      END IF
+	   END DO
+	   BULL_READ = MSG_NUM
+	   IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+	ELSE
+	   IF (MSG_NUM.EQ.0) RETURN
+	   SAVE_MSG_NUM = MSG_NUM
+	   PREV_MSG_NUM = MSG_NUM
+	   MSG_NUM = 0
+	   MSG_KEY = BULLDIR_HEADER
+	   IER = 0
+	   DO WHILE (IER.EQ.0.AND.MSG_NUM.LT.SAVE_MSG_NUM)
+	      IF (MSG_NUM.GT.0) THEN
+	         PREV_MSG_KEY = MSG_KEY
+	         PREV_MSG_NUM = MSG_NUM
+	      END IF
+	      CALL GET_NEXT_TAG(FN,IER,BULL_READ,TAG_TYPE)
+	   END DO
+	   IF (PREV_MSG_NUM.LT.SAVE_MSG_NUM) THEN
+	      MSG_NUM = PREV_MSG_NUM
+	      MSG_KEY = PREV_MSG_KEY
+	      CALL GET_THIS_OR_NEXT_TAG(FN,IER,BULL_READ,TAG_TYPE)
+	   ELSE
+	      IER = 36
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+	SUBROUTINE DECREMENT_MSG_KEY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	I = 1
+	DO WHILE (I.LT.9)
+	   ITEST = ICHAR(MSG_KEY(I:I))
+	   IF (ITEST.GT.0) THEN
+	      MSG_KEY(I:I) = CHAR(ITEST-1)
+	      I = 9
+	   ELSE
+	      I = I + 1
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_GENERIC(GENERIC)
+C
+C  SUBROUTINE SET_GENERIC
+C
+C  FUNCTION: Enables or disables "GENERIC" display, i.e. displaying
+C	general bulletins continually for a certain amount of days.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'(
+     &      '' ERROR: No privs to change GENERIC.'')')
+	   RETURN
+	END IF
+
+	IER = CLI$GET_VALUE('USERNAME',TEMP_USER)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_KEYNAME(TEMP_USER,IER)
+
+	IF (IER.EQ.0) THEN
+	   IF (GENERIC) THEN
+	      IF (CLI$PRESENT('DAYS')) THEN
+	         IER = CLI$GET_VALUE('DAYS',BULL_PARAMETER)
+	         CALL LIB$MOVC3(4,%REF(BULL_PARAMETER),NEW_FLAG(2))
+	      ELSE
+		 NEW_FLAG(2) = '   7'
+	      END IF
+	   ELSE
+	      NEW_FLAG(2) = 0
+	   END IF
+	   REWRITE (4) TEMP_USER//USER_ENTRY(13:)
+	ELSE
+	   WRITE (6,'('' ERROR: Specified username not found.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET_BRIEF_CONTINUOUS(BRIEF_CONTINUOUS)
+C
+C  SUBROUTINE SET_BRIEF_CONTINUOUS
+C
+C  FUNCTION: Enables or disables "BRIEF_CONTINUOUS" display, i.e. displaying
+C	the brief message continually until the new messages have been read.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+
+	IF (BRIEF_CONTINUOUS) THEN
+	   NEW_FLAG(2) = -1
+	ELSE
+	   NEW_FLAG(2) = 0
+	END IF
+
+	IF (IER.EQ.0) REWRITE (4) USER_ENTRY
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET_LOGIN(LOGIN)
+C
+C  SUBROUTINE SET_LOGIN
+C
+C  FUNCTION: Enables or disables bulletin display at login.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER TODAY*24
+
+	DIMENSION NOLOGIN_BTIM(2)
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'(
+     &      '' ERROR: No privs to change LOGIN.'')')
+	   RETURN
+	END IF
+
+	IER = CLI$GET_VALUE('USERNAME',TEMP_USER)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_KEYNAME(TEMP_USER,IER)
+
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NOLOGIN_BTIM)
+	IF (IER.EQ.0) THEN
+	   IF (LOGIN.AND.COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM).GE.0) THEN
+	      CALL SYS_BINTIM(TODAY,LOGIN_BTIM)
+	   ELSE IF (.NOT.LOGIN) THEN
+	      LOGIN_BTIM(1) = NOLOGIN_BTIM(1)
+	      LOGIN_BTIM(2) = NOLOGIN_BTIM(2)
+	   END IF
+	   REWRITE (4) TEMP_USER//USER_ENTRY(13:)
+	ELSE
+	   WRITE (6,'('' ERROR: Specified username not found.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_UAF(USERNAME,USER,GROUP,ACCOUNT,FLAGS,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER USERNAME*(*),ACCOUNT*(*)
+
+	INCLUDE '($UAIDEF)'
+
+	INTEGER*2 UIC(2)
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(4,UAI$_FLAGS,%LOC(FLAGS))
+	CALL ADD_2_ITMLST(LEN(ACCOUNT),UAI$_ACCOUNT,%LOC(ACCOUNT))
+	CALL ADD_2_ITMLST(4,UAI$_UIC,%LOC(UIC))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+
+	USER = UIC(1)
+	GROUP = UIC(2)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DCLEXH(EXIT_ROUTINE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER*4 EXBLK(4)
+
+	EXBLK(2) = EXIT_ROUTINE
+	EXBLK(3) = 1
+	EXBLK(4) = %LOC(EXBLK(4))
+
+	CALL SYS$DCLEXH(EXBLK(1))
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SENDMAIL(FILE,TO,SUBJECT,STATUS)
+
+        IMPLICIT INTEGER (A-Z)
+
+	PARAMETER CRLF = CHAR(13)//CHAR(10)
+
+	INCLUDE '($MAILDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /MAIL_INFO/ USE_INFROM
+	DATA USE_INFROM /.FALSE./
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+	DATA HEADER_Q1/0/
+
+	COMMON /SENDTO/ SENDTO
+	CHARACTER*256 SENDTO
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	COMMON /NEWSBULL/ NEWSBULL
+
+	CHARACTER*(*) FILE,TO,SUBJECT
+
+	EXTERNAL MAIL_ERROR
+
+	CALL SYS$SETAST(%VAL(1))
+
+	CALL DISABLE_PRIVS
+
+	SENDTO = TO
+        DO WHILE (INDEX(SENDTO,'""').GT.0)
+           SENDTO = SENDTO(:INDEX(SENDTO,'""'))//
+     &                   SENDTO(INDEX(SENDTO,'""')+2:)
+        END DO
+
+	DO WHILE (INDEX(SUBJECT,'""').GT.0)
+	   SUBJECT = SUBJECT(:INDEX(SUBJECT,'""'))//
+     &			 SUBJECT(INDEX(SUBJECT,'""')+2:)
+	END DO	
+
+	IF ((USE_INFROM.OR.NEWSBULL).AND.(SYS_TRNLNM('TWF$TCP','DEFINED').OR.
+     &	    SYS_TRNLNM('MULTINET_SOCKET_LIBRARY','DEFINED').OR.
+     &	    SYS_TRNLNM('UCX$DEVICE','DEFINED'))
+     &	    .AND..NOT.SYS_TRNLNM('BULL_DISABLE_SMTP','DEFINED')) THEN
+	   IER = SYS$ASCTIM(,INPUT,,)
+	   INPUT = INPUT(:2)//INPUT(4:6)//INPUT(10:11)//
+     &	      INPUT(13:14)//INPUT(16:17)//INPUT(19:20)//
+     &	      INPUT(22:23)
+	   IF (INPUT(:1).EQ.' ') INPUT = INPUT(2:)
+	   OPEN (UNIT=8,FILE=FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		INPUT(:TRIM(INPUT))//'.SMTP',IOSTAT=IER1,
+     &		STATUS='NEW',RECL=256)
+	   IF (IER1.EQ.0) THEN
+	      IF (LPATH.EQ.0) CALL GET_PATHNAME
+	      WRITE (8,'(A)',IOSTAT=IER) 'helo '//PATHNAME(2:LPATH)
+	      INPUT = INFROM
+	      I = INDEX(INPUT,'<')
+	      IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN 
+		 INPUT = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+	      END IF
+	      WRITE (8,'(A)',IOSTAT=IER) 'MAIL FROM:<'//
+     &			INPUT(:MINGT0(INDEX(INPUT,' ')-1,TRIM(INPUT)))//'>'
+	      SENDTO = SENDTO(INDEX(SENDTO,'"')+1:)
+	      DO WHILE (INDEX(SENDTO,'"').GT.0)
+		 SENDTO = SENDTO(:INDEX(SENDTO,'"')-1)//
+     &			  SENDTO(INDEX(SENDTO,'"')+1:)
+	      END DO
+	      WRITE (8,'(A)',IOSTAT=IER) 'RCPT TO:<'//SENDTO(:TRIM(SENDTO))
+     &					//'>'
+	      WRITE (8,'(A)',IOSTAT=IER) 'DATA'
+	      HEADER_Q = HEADER_Q1
+	      DO I=1,NHEAD
+		 CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+		 WRITE (8,'(A)',IOSTAT=IER) INPUT(:TRIM(INPUT))
+	      END DO
+	      IF (NHEAD.EQ.0.AND.TRIM(SUBJECT).GT.0) THEN
+		 WRITE (8,'(A)',IOSTAT=IER)
+     &			'Subject: '//SUBJECT(:TRIM(SUBJECT))
+		 WRITE (8,'(A)',IOSTAT=IER)
+	      END IF
+	      IF (NEWSBULL) THEN
+		 WRITE (8,'(A)') 'This message was posted via a folder'//
+     &		    ' with a news group associated with it.'
+		 WRITE (8,'(A)') 'It will continue to attempt to be'//
+     &		    ' posted to the news group using the file:'
+		 WRITE (8,'(A)') FILE(:TRIM(FILE))
+		 WRITE (8,'(A)') 'If necessary, you can either'//
+     &		    ' delete the file or edit it to fix it.'
+		 WRITE (8,'(A)') 'If you edit it, delete old versions.'
+		 WRITE (8,'(A)') ' '
+	      END IF
+	      OPEN (UNIT=3,FILE=FILE,STATUS='OLD',IOSTAT=IER)
+	      DO WHILE (IER.EQ.0)
+		 READ (3,'(Q,A)',IOSTAT=IER) L,INPUT
+		 IF (IER.EQ.0) THEN
+		    WRITE (8,'(A)',IOSTAT=IER) INPUT(:L)
+		 END IF
+	      END DO
+	      CLOSE (UNIT=3)
+	      REWIND (UNIT=8,IOSTAT=IER)
+	      IF (IER.NE.0) THEN
+	         CLOSE (UNIT=8,STATUS='DELETE')
+	         IER1 = 2
+	      END IF
+	   END IF
+	   IF (.NOT.SMTP_CONNECT()) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'220') GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('helo '//PATHNAME(2:LPATH)//CRLF))
+     &	       GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'250') GOTO 10
+	   INPUT = INFROM
+	   I = INDEX(INPUT,'<')
+	   IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN 
+	       INPUT = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+	   ELSE IF (I.EQ.0.AND.INDEX(INPUT,'@').EQ.0) THEN
+	       INPUT = INPUT(:TRIM(INPUT))//PATHNAME(:LPATH)
+	   END IF
+	   IF (.NOT.SMTP_WRITE_PACKET('MAIL FROM:<'//INPUT(:TRIM(INPUT))
+     &	       //'>'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'250') GOTO 10
+	   SENDTO = SENDTO(INDEX(SENDTO,'"')+1:)
+	   DO WHILE (INDEX(SENDTO,'"').GT.0)
+	      SENDTO = SENDTO(:INDEX(SENDTO,'"')-1)//
+     &			     SENDTO(INDEX(SENDTO,'"')+1:)
+	   END DO
+	   IF (.NOT.SMTP_WRITE_PACKET('RCPT TO:<'//SENDTO(:TRIM(SENDTO))
+     &				   //'>'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'250') GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('DATA'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'354') GOTO 10
+	   HEADER_Q = HEADER_Q1
+	   DO I=1,NHEAD
+	      CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+	      IF (BTEST(FOLDER_FLAG,15).OR.INPUT(:8).NE.'Subject:') THEN
+	         IF (.NOT.SMTP_WRITE_PACKET(INPUT(:TRIM(INPUT))//CRLF))
+     &		    GOTO 10
+	      ELSE
+	         IF (.NOT.SMTP_WRITE_PACKET('Subject: '//
+     &		    SUBJECT(:TRIM(SUBJECT))//CRLF)) GOTO 10
+	      END IF
+	   END DO
+	   IF (NHEAD.EQ.0.AND.TRIM(SUBJECT).GT.0) THEN
+	      IF (.NOT.SMTP_WRITE_PACKET('Subject: '//
+     &		    SUBJECT(:TRIM(SUBJECT))//CRLF)) GOTO 10
+	      NHEAD = 1
+	   END IF
+	   IF (.NOT.SMTP_WRITE_PACKET(CRLF)) GOTO 10
+	   IF (NEWSBULL) THEN
+	      IF (.NOT.SMTP_WRITE_PACKET('This message was posted via '//
+     &		'a folder with a news group associated with it.'//CRLF))
+     &		GOTO 10
+	      IF (.NOT.SMTP_WRITE_PACKET('It will continue to attempt to'//
+     &	   	' be posted to the news group using the file:'//CRLF))
+     &		GOTO 10
+	      IF (.NOT.SMTP_WRITE_PACKET(FILE(:TRIM(FILE))//CRLF)) GOTO 10
+	      IF (.NOT.SMTP_WRITE_PACKET('If necessary, you can either'//
+     &		' delete the file or edit it to fix it.'//CRLF)) GOTO 10
+	      IF (.NOT.SMTP_WRITE_PACKET('If you edit it, '//
+     &		'delete old versions.'//CRLF)) GOTO 10
+	      IF (.NOT.SMTP_WRITE_PACKET(CRLF)) GOTO 10
+	   END IF
+	   OPEN (UNIT=3,FILE=FILE,STATUS='OLD',IOSTAT=IER2)
+	   DO WHILE (IER2.EQ.0)
+	      READ (3,'(Q,A)',IOSTAT=IER2) L,INPUT
+	      IF (IER2.EQ.0) THEN
+		 IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) IER2 = 2
+	      END IF
+	   END DO
+	   CLOSE (UNIT=3)
+	   IF (IER2.EQ.2) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('.'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('QUIT'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IER2 = 1
+	   GOTO 20
+10	   IER2 = 2
+20	   CALL SMTP_DISCONNECT()
+	   IF (IER1.EQ.0) THEN
+	      IF (IER2) THEN
+		 CLOSE (UNIT=8,STATUS='DELETE')
+	      ELSE
+		 CLOSE (UNIT=8)
+	      END IF
+	   END IF
+	   CALL ENABLE_PRIVS
+	   STATUS = 1
+	   RETURN
+	END IF
+
+	C = 0
+
+	CALL LIB$ESTABLISH(MAIL_ERROR)
+
+	IER = SYS_TRNLNM('BULL_PERSONAL_NAME',INPUT)
+	IF (IER) THEN 
+           CALL INIT_ITMLST
+	   CALL ADD_2_ITMLST(TRIM(INPUT),MAIL$_SEND_PERS_NAME,
+     &				%LOC(INPUT))
+           CALL END_ITMLST(SEND_ITMLST)
+	   STATUS = MAIL$SEND_BEGIN(C,%VAL(SEND_ITMLST),0)
+	   IF (.NOT.STATUS) GO TO 100
+	ELSE
+	   STATUS = MAIL$SEND_BEGIN(C,0,0)
+	   IF (.NOT.STATUS) GO TO 100
+	END IF
+
+	J = 1
+	DO WHILE (J.LE.TRIM(SENDTO))
+	   I = INDEX(SENDTO(J:),',') - 1
+	   IF (I.EQ.-1) I = TRIM(SENDTO(J:))
+           CALL INIT_ITMLST
+           CALL ADD_2_ITMLST(I,MAIL$_SEND_USERNAME,
+     &			     %LOC(SENDTO(J:J+I-1)))
+           CALL END_ITMLST(ADDRESS_ITMLST)
+
+           STATUS = MAIL$SEND_ADD_ADDRESS(C,%VAL(ADDRESS_ITMLST),0)
+           IF (.NOT.STATUS) GO TO 100
+	   J = J + I
+	   IF (SENDTO(J:J).EQ.',') J = J + 1
+	END DO
+
+        CALL INIT_ITMLST
+        CALL ADD_2_ITMLST(TRIM(SUBJECT),MAIL$_SEND_SUBJECT
+     &				,%LOC(SUBJECT))
+        CALL ADD_2_ITMLST(TRIM(SENDTO),MAIL$_SEND_TO_LINE,%LOC(SENDTO))
+        CALL END_ITMLST(ATTRIBUTE_ITMLST)
+
+        STATUS = MAIL$SEND_ADD_ATTRIBUTE(C,%VAL(ATTRIBUTE_ITMLST),0)
+        IF (.NOT.STATUS) GO TO 100
+                                        
+        CALL INIT_ITMLST
+        CALL ADD_2_ITMLST(TRIM(FILE),MAIL$_SEND_FILENAME,%LOC(FILE))
+        CALL END_ITMLST(BODYPART_ITMLST)
+
+        STATUS = MAIL$SEND_ADD_BODYPART(C,%VAL(BODYPART_ITMLST),0)
+        IF (.NOT.STATUS) GO TO 100
+
+        STATUS = MAIL$SEND_MESSAGE(C,0,0)
+        IF (.NOT.STATUS) GO TO 100
+
+        STATUS = MAIL$SEND_END(C,0,0)
+        IF (.NOT.STATUS) GO TO 100
+
+100	CALL ENABLE_PRIVS
+	CALL LIB$REVERT
+
+        RETURN
+        END
+
+
+
+	FUNCTION MAIL_ERROR(SIGARGS,MECHARGS)
+
+	MAIL_ERROR = .TRUE.
+
+	CALL SYS$PUTMSG(SIGARGS,,)
+
+	RETURN
+	END
+
+
+
+
+        SUBROUTINE SET_NEWS
+
+        IMPLICIT INTEGER (A-Z)
+
+        INCLUDE '($SSDEF)'
+
+        INCLUDE 'BULLUSER.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+
+        INCLUDE 'BULLFILES.INC'
+
+        COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+        CHARACTER*64 BULL_PARAMETER
+	
+	EXTERNAL CLI$_NEGATED,CLI$_ABSENT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+	CHARACTER*80 BULLNEWSDIR_FILE
+
+	DIMENSION EXPIRED(2)
+
+	CHARACTER GROUP*44,FOLDER_SAVE*44,NEW_NEWS_ACCESS*132
+	CHARACTER NEWS_ACCESS*132
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: No privs to change NEWS.'')')
+	   RETURN
+	END IF
+
+	ENTRY SHOW_NEWS
+
+	LIMIT = -2
+	IF (CLI$GET_VALUE('LIMIT',BULL_PARAMETER,LEN_P)) THEN
+	   IER = OTS$CVT_TI_L(BULL_PARAMETER(:LEN_P),LIMIT,,%VAL(1))
+	   IF (.NOT.IER.OR.LIMIT.LT.-1) THEN
+	      WRITE (6,'('' ERROR: Invalid value for LIMIT.'')')
+	      RETURN
+	   END IF   
+	END IF	
+
+        EXPIRE = -1
+        IF (CLI$GET_VALUE('EXPIRATION',BULL_PARAMETER,LEN_P)) THEN
+           IER = OTS$CVT_TI_L(BULL_PARAMETER(:LEN_P),EXPIRE,,%VAL(1))
+	   IF (.NOT.IER.OR.(EXPIRE.LE.0.AND.CLI$PRESENT('DEFAULT'))) THEN
+	      WRITE (6,'('' ERROR: Invalid value for EXPIRATION.'')')
+	      RETURN
+	   END IF   
+        END IF
+
+	IF (.NOT.(CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('CLASS').OR.
+     &		CLI$PRESENT('SHOW_FOLDER')).AND.REMOTE_SET.LT.3) THEN 
+	   WRITE (6,'('' ERROR: You have not selected a news group.'')')
+           RETURN
+        END IF
+
+	CALL OPEN_BULLNEWS_SHARED	! Open folder file
+
+	IF (CLI$PRESENT('DEFAULT')) THEN
+	   CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+	ELSE IF (CLI$GET_VALUE('CLASS',BULL_PARAMETER,LEN_P)) THEN
+	   BULL_PARAMETER = BULL_PARAMETER(:LEN_P)//'.'
+	   CALL STR$UPCASE(BULL_PARAMETER,BULL_PARAMETER)
+	   LEN_P = LEN_P + 1
+	   IF (LEN_P.GT.LEN(FOLDER)) THEN
+	      WRITE (6,'('' ERROR: Class name too long.'')')
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+	   END IF
+	   GROUP = BULL_PARAMETER(:LEN_P)
+           LG = LEN_P
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(BULL_PARAMETER(:LEN_P),
+     &					NEWCLASS)
+	   IF (CLI$PRESENT('DELETE')) THEN
+	      IF (NEWCLASS.NE.0) THEN
+	         WRITE (6,'('' ERROR: Class not found.'')')
+	      ELSE
+	         DELETE (7)
+		 WRITE (6,'('' Class deleted.'')')
+	      END IF
+              IF (BTEST(FOLDER1_FLAG,0)) THEN
+		 OPEN (UNIT=3,FILE=NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	     	 CLOSE (UNIT=3,DISPOSE='DELETE')
+              END IF
+	      RETURN
+	   ELSE IF (NEWCLASS.NE.0) THEN
+              CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+              DO WHILE (IER.EQ.0)
+                 DO WHILE (REC_LOCK(IER))
+                    READ (7,KEY=NEWS_F1_COUNT,KEYID=1,IOSTAT=IER)
+                 END DO
+                 IF (IER.EQ.0) NEWS_F1_COUNT = NEWS_F1_COUNT + 1
+              END DO
+	      FOLDER1_FLAG = NEWS_FLAG_DEFAULT
+	      FOLDER1_BBEXPIRE = NEWS_EXPIRE_DEFAULT
+              F1_EXPIRE_LIMIT = NEWS_EXPIRE_LIMIT_DEFAULT
+ 	      CALL SYS_BINTIM('6-NOV-2956 00:00:00.00',EXPIRED)
+              CALL GET_MSGKEY(EXPIRED,NEWS_F1_EXPIRED_DATE)
+	      CALL SYS_BINTIM('5-NOV-1956 00:00:00.00',EXPIRED)
+              CALL GET_MSGKEY(EXPIRED,NEWS_F1_CREATED_DATE)
+	      FOLDER1_NUMBER = NEWS_F1_COUNT
+	      FOLDER1 = BULL_PARAMETER
+ 	      FOLDER1_FLAG = IBSET(FOLDER1_FLAG,10)
+	      CALL WRITE_FOLDER_FILE_TEMP(IER)
+	      IF (IER.NE.0) THEN
+		 CALL CLOSE_BULLNEWS
+		 WRITE (6,'('' Unable to add entry.'')')
+                 RETURN
+	      END IF	      
+	      TEMP = FOLDER1_NUMBER
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+	      NEWS_F1_COUNT = TEMP
+	      REWRITE (7) NEWS_FOLDER1_COM
+ 	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(TEMP,IER)
+	   END IF	
+ 	ELSE
+	   IF (CLI$GET_VALUE('SHOW_FOLDER',FOLDER1).EQ.
+     &				%LOC(CLI$_ABSENT)) FOLDER1 = FOLDER
+	   IF (INDEX(FOLDER1,'.').GT.0) CALL LOWERCASE(FOLDER1)
+       	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR: Invalid news group.'')')
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+	   END IF
+	END IF
+
+ 	IF (EXPIRE.GE.0) FOLDER1_BBEXPIRE = EXPIRE
+	IF (LIMIT.GE.-1) F1_EXPIRE_LIMIT = LIMIT
+
+	CLASS = CLI$PRESENT('CLASS')
+	DEFAULT = CLI$PRESENT('DEFAULT')
+	ALL = CLI$PRESENT('ALL')
+ 	IF (CLASS.AND.INDEX(GROUP(:LG-1),'.').GT.0) ALL = .TRUE.
+	DISABLE = CLI$PRESENT('DISABLE')
+      	ENABLE = CLI$PRESENT('ENABLE')
+     	PRIVATE = CLI$PRESENT('PRIVATE')
+     	NOPRIVATE = CLI$PRESENT('PRIVATE').EQ.%LOC(CLI$_NEGATED)
+	
+	STORED = 0
+	IF (CLI$PRESENT('STORED')) THEN
+	   STORED = 1
+	   IF (.NOT.(CLASS.OR.DEFAULT).AND..NOT.BTEST(FOLDER1_FLAG,8)) THEN 
+	      F1_LAST = 0
+	      F1_COUNT = 0
+	      F1_START = 0
+	      F1_NBULL = 0
+	      NEWS_F1_FIRST = 0
+	      NEWS_F1_END = 0
+           END IF
+	   FOLDER1_FLAG = IBSET(FOLDER1_FLAG,8)
+	ELSE IF (CLI$PRESENT('STORED').EQ.%LOC(CLI$_NEGATED)) THEN   
+	   STORED = 2
+	   CALL GET_INPUT_PROMPT(BULL_PARAMETER,LEN_P,
+     &      'Are you sure you want to remove stored setting? '//
+     &	    '(Y/N with N as default): ')
+	   IF (BULL_PARAMETER(:1).NE.'y'.AND.BULL_PARAMETER(:1).NE.'Y') THEN
+	      WRITE (6,'('' Stored setting was not removed.'')')
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+           END IF
+	   IF (DEFAULT) THEN
+	      CALL LIB$DELETE_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &			//'[.BULLNEWS*]*.*;*')
+	      CALL LIB$DELETE_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &			//'BULLNEWS*.DIR;*')
+	   ELSE IF (.NOT.CLASS.AND.BTEST(FOLDER1_FLAG,8)) THEN
+              CALL CLOSE_BULLNEWS
+	      FOLDER_SAVE = FOLDER
+	      IF (FOLDER_NUMBER.NE.FOLDER1_NUMBER) THEN
+                 FOLDER_NUMBER = FOLDER1_NUMBER
+                 CALL SELECT_FOLDER(.FALSE.,IER)
+	      END IF
+	      FOLDER = FOLDER_SAVE
+              CALL OPEN_BULLDIR
+	      CALL CLOSE_BULLDIR_DELETE
+              CALL OPEN_BULLNEWS_SHARED 
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(NEWS_FOLDER_NUMBER,IER)
+	      F1_START = 0
+	      F1_NBULL = 0
+	      F1_COUNT = 0 
+              F1_LAST = 0
+           END IF
+           FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,8)
+	   FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,13)
+        END IF
+
+	IF (NOPRIVATE.AND..NOT.DEFAULT) THEN
+	   OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	   CLOSE (UNIT=3,DISPOSE='DELETE')
+	   FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+	END IF
+
+	IF (PRIVATE.AND..NOT.BTEST(FOLDER1_FLAG,0)) THEN
+	   CALL SET_PROTECTION
+	   OPEN (UNIT=3,FILE=NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	   CLOSE (UNIT=3)
+	   IF (IER.NE.0) THEN	
+	      OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &			STATUS='NEW',IOSTAT=IER)
+	      CLOSE (UNIT=3)
+	   END IF
+	   CALL RESET_PROTECTION
+	   FOLDER1_FLAG = IBSET(FOLDER1_FLAG,0)
+	END IF
+
+	IF (ENABLE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,9)
+	IF (DISABLE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,9)
+
+	FLAG = ENABLE.OR.DISABLE.OR.STORED.NE.0.OR.PRIVATE.OR.NOPRIVATE
+
+        CALL REWRITE_FOLDER_FILE_TEMP(IER)
+
+        IF (DEFAULT.OR.(CLASS.AND.(STREQ(GROUP(:LG),FOLDER(:LG))
+     &		.OR.STREQ(GROUP(:LG-1),FOLDER)))) THEN 
+           NEWS_FLAG_DEFAULT = NEWS_F1_FLAG
+           NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+           NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	END IF
+
+        CALL OTS$CVT_L_TI(FOLDER1_BBEXPIRE,BULL_PARAMETER,,,)
+        IF (DEFAULT.OR.CLASS) THEN
+	   IF (CLASS) THEN
+              WRITE (6,'('' For class '',A,'':'')') GROUP(:LG)
+	   END IF
+           IF (BTEST(FOLDER1_FLAG,9)) WRITE (6,'('' Disable is set.'')')	
+           IF (BTEST(FOLDER1_FLAG,8)) THEN
+              WRITE (6,'('' Default is stored.'')')
+           ELSE
+              WRITE (6,'('' Default is not stored.'')')
+           END IF
+           CALL OTS$CVT_L_TI(FOLDER1_BBEXPIRE,BULL_PARAMETER,,,)
+           IF (FOLDER1_BBEXPIRE.GT.0) THEN
+              WRITE (6,'('' Default expiration for stored groups is ''
+     &         ,A,''.'')') BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+           ELSE IF (CLASS) THEN
+              WRITE (6,'('' Expiration is DEFAULT value.'')')
+           ELSE
+              WRITE (6,'('' Default expiration for stored groups is ''
+     &			 ,''14.'')')
+           END IF
+           CALL OTS$CVT_L_TI(F1_EXPIRE_LIMIT,BULL_PARAMETER,,,)
+           IF (F1_EXPIRE_LIMIT.GT.0) THEN
+              WRITE (6,'('' Default expiration limit is '',A,''.'')')
+     &                  BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+           ELSE IF (CLASS.AND.F1_EXPIRE_LIMIT.EQ.0) THEN 
+              WRITE (6,'('' Expiration limit is DEFAULT value.'')')
+           ELSE
+              WRITE (6,'('' There is no default expiration limit.'')')
+           END IF
+           IF (BTEST(FOLDER1_FLAG,0)) THEN
+              WRITE (6,'('' Private is set.'')')
+           END IF
+        ELSE IF (BTEST(FOLDER1_FLAG,9)) THEN
+	   FOLDER1_NAME = FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,' ')-1)
+           WRITE (6,'('' For news group '',A,'':'')') 
+     &			FOLDER1_NAME(:TRIM(FOLDER1_NAME))
+           WRITE (6,'('' Disable is set.'')')
+	ELSE
+	   FOLDER1_NAME = FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,' ')-1)
+           WRITE (6,'('' For news group '',A,'':'')') 
+     &			FOLDER1_NAME(:TRIM(FOLDER1_NAME))
+           IF (BTEST(FOLDER1_FLAG,8)) THEN
+              WRITE (6,'('' News group is stored.'')')
+              CALL OTS$CVT_L_TI(FOLDER1_BBEXPIRE,BULL_PARAMETER,,,)
+              IF (FOLDER1_BBEXPIRE.GT.0) THEN
+                 WRITE (6,'('' Expiration is '',A,''.'')')
+     &                  BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+              ELSE
+                 WRITE (6,'('' Expiration is DEFAULT value.'')')
+              END IF
+           ELSE
+              WRITE (6,'('' News group is not stored.'')')
+	   END IF
+           CALL OTS$CVT_L_TI(F1_EXPIRE_LIMIT,BULL_PARAMETER,,,)
+           IF (F1_EXPIRE_LIMIT.GT.0) THEN
+              WRITE (6,'('' Expiration limit is '',A,''.'')')
+     &                  BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+           ELSE IF (F1_EXPIRE_LIMIT.EQ.0) THEN 
+              WRITE (6,'('' Expiration limit is DEFAULT value.'')')
+           ELSE
+              WRITE (6,'('' There is no expiration limit.'')')
+           END IF
+	   IF (BTEST(FOLDER1_FLAG,1)) THEN
+	      WRITE (6,'('' DUMP has been set.'')')
+	   END IF
+           IF (BTEST(FOLDER1_FLAG,0)) THEN
+              WRITE (6,'('' Private is set.'')')
+           END IF
+           NOTIFY_FLAG_NEWS = .FALSE.
+           SET_FLAG_NEWS = .FALSE.
+	   BRIEF_FLAG_NEWS = .FALSE.
+ 	   CALL OPEN_BULLINF_SHARED
+           DO WHILE (REC_LOCK(IER1))
+              READ (9,KEY='*DEFAULT',IOSTAT=IER1) TEMP_USER,INF_REC
+       	   END DO
+	   IF (IER1.EQ.0) THEN
+	      I = 1
+              DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	         I = I + 1
+       	      END DO
+	      IF (I.LE.FOLDER_MAX-1) THEN
+	         NOTIFY_FLAG_NEWS = BTEST(INF_REC2(2,I),13)
+	         SET_FLAG_NEWS = BTEST(INF_REC2(2,I),14)
+	         BRIEF_FLAG_NEWS = BTEST(INF_REC2(2,I),15)
+		 WRITE (6,'('' This is a default news group.'')')
+              ELSE
+	         IER1 = 2
+	      END IF
+           END IF
+           NOTIFY_PERM_FLAG_NEWS = .FALSE.
+           SET_PERM_FLAG_NEWS = .FALSE.
+	   BRIEF_PERM_FLAG_NEWS = .FALSE.
+           DO WHILE (REC_LOCK(IER2))
+              READ (9,KEY='*PERM',IOSTAT=IER2) TEMP_USER,INF_REC
+       	   END DO
+	   IF (IER2.EQ.0) THEN
+	      I = 1
+              DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	         I = I + 1
+       	      END DO
+	      IF (I.LE.FOLDER_MAX-1) THEN
+	         NOTIFY_PERM_FLAG_NEWS = BTEST(INF_REC2(2,I),13)
+	         SET_PERM_FLAG_NEWS = BTEST(INF_REC2(2,I),14)
+	         BRIEF_PERM_FLAG_NEWS = BTEST(INF_REC2(2,I),15)
+		 WRITE (6,'('' This is a permanent news group.'')')
+	      END IF
+           END IF
+	   PERM = .FALSE.
+	   IF (SET_FLAG_NEWS) THEN
+	      IF (BRIEF_FLAG_NEWS) THEN
+	         IF (SET_PERM_FLAG_NEWS.AND.BRIEF_PERM_FLAG_NEWS) THEN
+	            PERM = .TRUE.
+		    WRITE (6,'('' Default is BRIEF, which is permanent.'')')
+		 ELSE
+		    WRITE (6,'('' Default is BRIEF.'')')
+		 END IF
+	      ELSE
+	        IF (SET_PERM_FLAG_NEWS.AND..NOT.BRIEF_PERM_FLAG_NEWS) THEN
+	           PERM = .TRUE.
+		   WRITE (6,'('' Default is READNEW, which is permanent.'')')
+		ELSE
+		   WRITE (6,'('' Default is READNEW.'')')
+		END IF
+	      END IF
+	   ELSE IF (BRIEF_FLAG_NEWS) THEN
+	      IF (.NOT.SET_PERM_FLAG_NEWS.AND.BRIEF_PERM_FLAG_NEWS) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is SHOWNEW, which is permanent.'')')
+	      ELSE
+		 WRITE (6,'('' Default is SHOWNEW.'')')
+    	      END IF
+	   END IF
+	   IF (.NOT.PERM) THEN
+	    IF (SET_PERM_FLAG_NEWS.AND.BRIEF_PERM_FLAG_NEWS) THEN
+	      	WRITE (6,'('' BRIEF is the permanent setting.'')')
+	    ELSE IF (SET_PERM_FLAG_NEWS.AND..NOT.BRIEF_PERM_FLAG_NEWS) THEN
+		WRITE (6,'('' READNEW is the permanent setting.'')')
+	    ELSE IF (BRIEF_PERM_FLAG_NEWS.AND..NOT.SET_PERM_FLAG_NEWS) THEN
+		WRITE (6,'('' SHOWNEW is the permanent setting.'')')
+	    END IF
+	   END IF
+	   IF (NOTIFY_FLAG_NEWS) THEN
+	      IF (NOTIFY_PERM_FLAG_NEWS) THEN
+		 WRITE (6,'('' Default is NOTIFY, which is permanent.'')')
+	      ELSE IF (IER1.EQ.0) THEN
+		 WRITE (6,'('' Default is NOTIFY.'')')
+	      END IF
+	   ELSE IF (NOTIFY_PERM_FLAG_NEWS) THEN
+	      WRITE (6,'('' NOTIFY is permanent.'')')
+	   ELSE IF (IER1.EQ.0) THEN
+ 	      WRITE (6,'('' Default is NONOTIFY.'')')
+	   END IF
+	   CALL CLOSE_BULLINF
+ 	END IF
+
+	IF (CLI$PRESENT('FULL').AND.BTEST(FOLDER1_FLAG,0)) THEN
+	   CALL CHKACL(NEWS_ACCESS(FOLDER1_DESCRIP),IER)
+	   IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.IER) THEN
+	      IF (SETPRV_PRIV()) THEN
+	         READ_ACCESS = 1
+		 WRITE_ACCESS = 1
+	      ELSE
+	        CALL CHECK_ACCESS(NEWS_ACCESS(FOLDER1_DESCRIP),
+     &		   USERNAME,READ_ACCESS,WRITE_ACCESS)
+	      END IF
+	      IF (WRITE_ACCESS) CALL SHOWACL(NEWS_ACCESS(FOLDER1_DESCRIP))
+	   ELSE IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	      WRITE (6,'('' Access is not limited.'')')
+	   END IF
+	END IF
+
+        IF (EXPIRE.LT.0.AND.LIMIT.LT.-1.AND..NOT.FLAG.AND.
+     &		(.NOT.CLASS.OR.NEWCLASS.EQ.0)) THEN 
+	   CALL CLOSE_BULLNEWS
+	   RETURN
+	END IF
+
+ 	IF (CLASS.AND.(ALL.OR.FLAG)) THEN
+           WRITE (6,'('' Modifying news groups...'')')
+	   FOLDER_SAVE = FOLDER
+	   CALL LOWERCASE(GROUP)
+           CALL READ_FOLDER_FILE_KEYNAME_TEMP(GROUP(:LG-1),IER)
+	   IF (IER.NE.0.OR.GROUP(:LG-1).NE.FOLDER1) THEN
+	      CALL READ_FOLDER_FILE_KEYNAMEGE_TEMP(GROUP(:LG),IER)
+	   END IF
+	   FOUND = .FALSE.
+	   MODALL = INDEX(GROUP,'.').NE.LG
+           DO WHILE (IER.EQ.0.AND.(GROUP(:LG).EQ.FOLDER1(:LG).OR.
+     &			GROUP(:LG).EQ.FOLDER1(:TRIM(FOLDER1))//'.'))
+ 	      FOUND = .TRUE.
+	      IF (STORED.EQ.2.AND.BTEST(FOLDER1_FLAG,8)) THEN 
+	         CALL CLOSE_BULLNEWS
+                 FOLDER_NUMBER = -1
+                 CALL SELECT_FOLDER(.FALSE.,IER)
+	         IF (IER) THEN
+                    CALL OPEN_BULLDIR
+                    CALL CLOSE_BULLDIR_DELETE
+	         END IF
+	         CALL OPEN_BULLNEWS_SHARED
+           	 CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+                 F1_LAST = 0
+                 F1_COUNT = 0
+		 F1_START = 0
+		 F1_NBULL = 0
+	         FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,8) 
+	         FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,13)
+	      ELSE IF (STORED.EQ.1.AND..NOT.BTEST(FOLDER1_FLAG,8)) THEN
+	         F1_LAST = 0
+                 F1_COUNT = 0
+		 F1_START = 0
+		 F1_NBULL = 0
+		 NEWS_F1_FIRST = 0
+                 NEWS_F1_END = 0
+	         FOLDER1_FLAG = IBSET(FOLDER1_FLAG,8)
+              END IF
+              IF (EXPIRE.GE.0) FOLDER1_BBEXPIRE = 0
+              IF (EXPIRE.GE.0.AND.MODALL) FOLDER1_BBEXPIRE = EXPIRE
+              IF (LIMIT.GE.0) F1_EXPIRE_LIMIT = 0
+              IF (LIMIT.GE.0.AND.MODALL) F1_EXPIRE_LIMIT = LIMIT
+	      IF (ENABLE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,9)
+	      IF (DISABLE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,9)
+	      IF (PRIVATE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,0)
+	      IF (NOPRIVATE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+              CALL REWRITE_FOLDER_FILE_TEMP(IER)
+              CALL READ_FOLDER_FILE_KEYNAMEGT_TEMP(FOLDER1,IER)
+           END DO
+	   IF (.NOT.FOUND) THEN
+	      WRITE (6,'('' ERROR: No news groups match class name.'')') 
+	      WRITE (6,'('' ERROR: Class has been removed.'')') 
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL STR$UPCASE(GROUP,GROUP)
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(GROUP(:LG),IER)
+              DELETE (7) 
+	      CALL CLOSE_BULLNEWS
+	      OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	      CLOSE (UNIT=3,DISPOSE='DELETE')
+	   END IF
+	   IF (FOLDER_SAVE.NE.FOLDER) THEN 
+              FOLDER_NUMBER = -1
+	      FOLDER1 = FOLDER_SAVE
+              CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (.NOT.IER) THEN 
+	         FOLDER_NUMBER = 0
+	         CALL SELECT_FOLDER(.FALSE.,IER)
+                 WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &              FOLDER(:TRIM(FOLDER))
+	      END IF
+	      RETURN
+           END IF
+ 	ELSE IF (DEFAULT.AND.(ALL.OR.FLAG)) THEN
+           WRITE (6,'('' Modifying news groups.'',
+     &			''  This will take a while...'')')
+	   IER = 0
+	   DO WHILE (IER.EQ.0)
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+              IF (EXPIRE.GE.0) FOLDER1_BBEXPIRE = 0
+              IF (LIMIT.GE.0) F1_EXPIRE_LIMIT = 0
+	      IF ((STORED.EQ.1.AND..NOT.BTEST(FOLDER1_FLAG,8)).OR.
+     &		  (STORED.EQ.2.AND.BTEST(FOLDER1_FLAG,8))) THEN 
+                 F1_LAST = 0
+                 F1_COUNT = 0
+		 F1_START = 0
+		 F1_NBULL = 0
+		 NEWS_F1_FIRST = 0
+                 NEWS_F1_END = 0
+              END IF
+	      IF (STORED.EQ.1) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,8)
+	      IF (STORED.EQ.2) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,8)
+	      IF (STORED.EQ.2) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,13)
+	      IF (ENABLE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,9)
+	      IF (DISABLE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,9)
+	      CALL REWRITE_FOLDER_FILE_TEMP(IER)
+	   END DO	   
+	END IF
+
+	FOLDER_NUMBER = -1
+	FOLDER1 = FOLDER
+        CALL SELECT_FOLDER(.FALSE.,IER)
+	IF (.NOT.IER) THEN 
+	   FOLDER_NUMBER = 0
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+           WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &        FOLDER(:TRIM(FOLDER))
+	END IF
+
+	CALL CLOSE_BULLNEWS
+
+        RETURN
+        END
+
+
+
+
+	SUBROUTINE INCLUDE(EXCLUDE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+ 	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER TODAY*24
+
+	DIMENSION BTIM(2)
+
+	ALL = CLI$PRESENT('ALL')
+	FULL = CLI$PRESENT('FULL')
+	IF (.NOT.CLI$GET_VALUE('P1',INPUT,LEN_P).AND..NOT.ALL) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	      WRITE(6,'('' ERROR: You have not read any message.'')')
+	      RETURN			! And return
+	   END IF
+
+	   CALL OPEN_BULLDIR_SHARED
+
+	   BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,1)
+	   CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+	   BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+
+       	   IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	      WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      CALL CLOSE_BULLDIR		! If not, then error out
+	      RETURN
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED	! Open BULLETIN file
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (CLI$PRESENT('SUBJECT')) THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      ELSE
+	         INPUT = INPUT(7:) 
+	         IF (INDEX(INPUT,'%"').GT.0) THEN
+	            INPUT = INPUT(INDEX(INPUT,'%"')+2:ILEN-1)
+	         END IF
+	      END IF
+	   ELSE
+	      INPUT = FROM
+	   END IF
+	   IF (CLI$PRESENT('SUBJECT')) THEN
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	         INPUT = INPUT(7:)
+	      ELSE
+		 INPUT = DESCRIP
+	      END IF
+	   END IF
+	   LEN_P = TRIM(INPUT)
+	   CALL CLOSE_BULLFIL
+	END IF
+
+	SUB = CLI$PRESENT('SUBJECT')
+	DISABLE = CLI$PRESENT('DISABLE')
+	EXC = 0
+
+	GO TO 5
+
+	ENTRY INCLUDE_SUBJECT(EXCLUDE)
+
+	IF (REMOTE_SET.GE.3.AND.NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) RETURN
+
+	LEN_P = TRIM(INPUT)
+	ALL = .FALSE.
+	DISABLE = .FALSE.
+	SUB = .TRUE.
+	EXC = -1
+
+5	IF (SUB) THEN
+	   IF (DISABLE) THEN
+	      IF (STREQ(INPUT(:3),'RE:')) INPUT = INPUT(5:)
+	      INPUT = INPUT(:MIN(LEN_P,LEN(DESCRIP)))
+	      LEN_P = TRIM(INPUT)
+	   END IF
+	   INPUT = 'SUBJECT:'//INPUT
+	   LEN_P = LEN_P + 8
+	ELSE
+	   INPUT = 'FROM:'//INPUT
+	   LEN_P = LEN_P + 5
+	END IF
+
+	IF (EXCLUDE) THEN
+	   INPUT = ':exclude:'//INPUT
+	   LEN_P = LEN_P + 9
+	ELSE
+	   INPUT = ':include:'//INPUT
+	   LEN_P = LEN_P + 9
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	L_TODAY = TRIM(TODAY)
+
+	FLEN = TRIM(FOLDER_NAME)
+	INPUT = FOLDER_NAME(:FLEN)//INPUT
+    	ILEN = FLEN + LEN_P
+
+	IF (EXC.EQ.0) THEN
+	   EXC = -1
+	   IER = CLI$GET_VALUE('LIMIT',BULL_PARAMETER,LEN_P)
+	   IF (IER) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER,IOSTAT=IER) EXC
+	      IF (EXC.LT.0.OR.EXC.GT.999.OR.IER.NE.0) THEN 
+	         WRITE(6,'('' ERROR: Valid limit is 0-999.'')')
+	         RETURN
+	      END IF
+	   END IF
+	END IF
+
+	CHECK_ONLY = .FALSE.
+
+	GO TO 100
+
+	ENTRY CHECK_EXCLUDES
+
+	CHECK_ONLY = .TRUE.
+	DISABLE = .TRUE.
+	LEN_P = 0
+	INPUT = ' '
+	ILEN = 1
+
+100	IER = SYS_TRNLNM('BULL_USER_CUSTOM',BULL_PARAMETER)
+	IF (.NOT.IER) BULL_PARAMETER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	CALL DISABLE_PRIVS
+
+	OPEN(UNIT=3,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER1,RECL=INPUT_LENGTH)
+
+	OPEN(UNIT=4,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    DISPOSE='DELETE',CARRIAGECONTROL='LIST',STATUS='NEW',
+     &	    SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	CALL ENABLE_PRIVS
+
+	IF (IER.NE.0) THEN
+	   CLOSE (UNIT=3)
+	   WRITE(6,'('' ERROR: Error in opening new custom file.'')')
+	   RETURN
+	END IF
+
+	IF (IER1.NE.0) THEN
+	   IF (.NOT.DISABLE.AND.LEN_P.GT.0) THEN 
+	      CALL ADD_EXCL(INPUT,ILEN,EXC)
+	      WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	   CLOSE (UNIT=4,DISPOSE='SAVE')
+	   RETURN
+	END IF
+
+	IER = 0
+	CONVERT = .FALSE.
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER) OLEN,OLD_BUFFER
+	   I = STRFIND(OLD_BUFFER,':RE: ')
+	   IF (IER.EQ.0) THEN
+	      IF (INDEX(OLD_BUFFER(FLEN+2:),'defaults').EQ.1.AND.FULL
+     &		.AND.INPUT(:FLEN).EQ.OLD_BUFFER(:MIN(FLEN,OLEN))) THEN
+		 I = INDEX(OLD_BUFFER,':kill')
+		 IF (DISABLE.AND.I.GT.0) THEN
+		    IF (I.GT.FLEN-1.OR.OLEN.GT.I+4) THEN
+		       OLD_BUFFER = OLD_BUFFER(:I-1)//OLD_BUFFER(I+5:)
+		       WRITE (4,'(A)',IOSTAT=IER) OLD_BUFFER(:OLEN-5)
+		    END IF
+	         ELSE IF (.NOT.DISABLE.AND.I.EQ.0) THEN
+		    OLD_BUFFER = OLD_BUFFER(:OLEN)//':kill'
+		    WRITE (4,'(A)',IOSTAT=IER) OLD_BUFFER(:OLEN+5)
+		    FULL = .FALSE.
+	         END IF
+	      ELSE IF ((STREQ(OLD_BUFFER(:ILEN),INPUT(:ILEN)).AND.
+     &		OLD_BUFFER(ILEN+1:ILEN+1).EQ.':').OR.
+     &		(OLEN.LT.ILEN.AND.INPUT(OLEN+1:OLEN+1).EQ.':'.AND.
+     &		 STREQ(OLD_BUFFER(:OLEN),INPUT(:OLEN))).OR.
+     &	         (DISABLE.AND.I.GT.0.AND.
+     &	         ((STREQ(OLD_BUFFER(:I)//OLD_BUFFER(I+5:MAX(I+5,ILEN+4)),
+     &		   INPUT(:ILEN)).AND.OLD_BUFFER(ILEN+5:ILEN+5).EQ.':').OR.
+     &		   (OLEN.LT.ILEN.AND.INPUT(OLEN+1:OLEN+1).EQ.':'.AND.
+     &		    STREQ(OLD_BUFFER(:I)//OLD_BUFFER(I+5:OLEN),
+     &		    INPUT(:OLEN)))))) THEN 
+	         CONTINUE
+ 	      ELSE IF (.NOT.(ALL.AND.STREQ(INPUT(:FLEN+8),
+     &		OLD_BUFFER(:MIN(FLEN+8,OLEN))))) THEN
+		 IER2 = OLD_BUFFER(:1).EQ.':'.OR.
+     &			INDEX(OLD_BUFFER,':defaults:').GT.0
+		 IF (.NOT.IER2) THEN
+		    CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC1,BLIMIT,BDATE,IER1)
+		    IF (IER1) IER2 = COMPARE_DATE(OLD_BUFFER(BDATE:OLEN-1)
+     &		    		     ,' ').GT.-EXC1
+		    CONVERT = .NOT.IER1
+		 END IF
+		 IF (.NOT.IER1.OR.EXC1.EQ.0.OR.IER2)
+     &	            WRITE (4,'(A)',IOSTAT=IER) OLD_BUFFER(:OLEN)
+	      END IF
+	   END IF
+	END DO
+
+	IF (.NOT.DISABLE) THEN
+	   IF (FULL) THEN
+	      WRITE (4,'(A)',IOSTAT=IER) FOLDER_NAME(:FLEN)//':defaults:kill'
+	   ELSE
+	      CALL ADD_EXCL(INPUT,ILEN,EXC)
+	      WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	END IF
+
+	IF (CONVERT) THEN 
+	   WRITE (6,'('' NOTE: See help on the new SET EXLIMIT command.'')')
+	END IF
+
+	CLOSE (UNIT=4,DISPOSE='SAVE')
+	CLOSE (UNIT=3,DISPOSE='DELETE')
+
+	CALL LIB$RENAME_FILE(BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &			     BULL_PARAMETER(:TRIM(BULL_PARAMETER))//';1')
+    
+	IF (.NOT.CHECK_ONLY) CALL CHECK_CUSTOM
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_EXCLUDE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+	DATA SCRATCH_B1/0/,NINCLUDE/0/,EXC_CHANGED/.FALSE./
+
+	CHARACTER TODAY*24
+
+	DIMENSION BTIM(2)
+
+	IF (.NOT.EXC_CHANGED) RETURN
+	EXC_CHANGED = .FALSE.
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	L_TODAY = TRIM(TODAY)
+
+	IER = SYS_TRNLNM('BULL_USER_CUSTOM',BULL_PARAMETER)
+	IF (.NOT.IER) BULL_PARAMETER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	CALL DISABLE_PRIVS
+
+	OPEN(UNIT=3,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER1,RECL=INPUT_LENGTH)
+
+	OPEN(UNIT=4,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    DISPOSE='DELETE',CARRIAGECONTROL='LIST',STATUS='NEW',
+     &	    SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	CALL ENABLE_PRIVS
+
+	IF (IER.NE.0) THEN
+	   CLOSE (UNIT=3)
+	   WRITE(6,'('' ERROR: Error in opening new custom file.'')')
+	   RETURN
+	END IF
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	   IF (.NOT.(IER.EQ.0.AND.FOLDER_NAME(:TRIM(FOLDER_NAME))//':'.EQ.
+     &		INPUT(:MIN(TRIM(FOLDER_NAME)+1,ILEN)).AND.INPUT(:1).NE.':'
+     & 		.AND.INDEX(INPUT,':defaults:').EQ.0)) THEN 
+	      IF (IER.EQ.0) WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	END DO
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+	DO I=1,NINCLUDE
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,INPUT)
+	   WRITE (4,'(A)',IOSTAT=IER) INPUT(:TRIM(INPUT))
+	END DO
+
+	CLOSE (UNIT=4,DISPOSE='SAVE')
+	CLOSE (UNIT=3,DISPOSE='DELETE')
+
+	CALL LIB$RENAME_FILE(BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &			     BULL_PARAMETER(:TRIM(BULL_PARAMETER))//';1')
+
+	IF (.NOT.CHECK_ONLY) CALL CHECK_CUSTOM
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_CUSTOM(PARAM)
+C
+C  SUBROUTINE SET_CUSTOM
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EXCLUDE_LIMIT/ EXCLUDE_LIMIT
+	DATA EXCLUDE_LIMIT /0/
+
+	CHARACTER*(*) PARAM
+
+	IER = SYS_TRNLNM('BULL_USER_CUSTOM',BULL_PARAMETER)
+	IF (.NOT.IER) BULL_PARAMETER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	CALL DISABLE_PRIVS
+
+	OPEN(UNIT=3,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER1,RECL=INPUT_LENGTH)
+
+	OPEN(UNIT=4,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    DISPOSE='DELETE',CARRIAGECONTROL='LIST',STATUS='NEW',
+     &	    SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	CALL ENABLE_PRIVS
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Error in opening custom file.'')')
+	   RETURN
+	END IF
+
+	LENP = LEN(PARAM)
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	   IF (IER.EQ.0.AND.PARAM(:LENP).NE.INPUT(2:LENP+1)) THEN
+              WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	END DO
+
+	IF (CLI$GET_VALUE('SET_PARAM2',INPUT,ILEN)) THEN
+	   WRITE (4,'(A)',IOSTAT=IER) ':'//PARAM(:LENP)//':'//INPUT(:ILEN)
+	END IF
+
+	IF (PARAM.EQ.'exclude_limit')
+     &		DECODE(ILEN,'(I<ILEN>)',INPUT(:ILEN)) EXCLUDE_LIMIT
+
+	CLOSE (UNIT=4,DISPOSE='SAVE')
+	CLOSE (UNIT=3,DISPOSE='DELETE')
+
+	CALL LIB$RENAME_FILE(BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &			     BULL_PARAMETER(:TRIM(BULL_PARAMETER))//';1')
+
+	CALL CHECK_CUSTOM
+
+        RETURN
+        END
+
+
+
+
+	SUBROUTINE CHECK_CUSTOM
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+
+	COMMON /FILE_DIRECTORY/ FILE_DIRECTORY
+	CHARACTER*64 FILE_DIRECTORY
+
+	COMMON /EXCLUDE_LIMIT/ EXCLUDE_LIMIT
+	DATA EXCLUDE_LIMIT /0/
+
+	DIMENSION BTIM(2)
+
+	FILE_DIRECTORY = ' '
+
+	IF (.NOT.BTEST(BULL_USER_CUSTOM,4)) THEN
+	   BULL_USER_CUSTOM = .FALSE.
+	ELSE
+	   BULL_USER_CUSTOM = .FALSE.
+	   BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,4)
+	END IF
+
+	IER = SYS_TRNLNM('BULL_USER_CUSTOM',OLD_BUFFER)
+	IF (.NOT.IER) OLD_BUFFER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	OPEN(UNIT=17,FILE=OLD_BUFFER(:TRIM(OLD_BUFFER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	IF (IER.NE.0) RETURN
+
+	IF (SCRATCH_B1.NE.0) THEN		! Is queue empty?
+	   SCRATCH_B = SCRATCH_B1		! No, set queue pointer to head
+	ELSE					! Else if queue is empty
+	   CALL INIT_QUEUE(SCRATCH_B,OLD_BUFFER)
+	   SCRATCH_B1 = SCRATCH_B		! Init header pointer
+	END IF
+
+	NINCLUDE = 0
+	OLD_FORMAT = .FALSE.
+	FLEN = TRIM(FOLDER_NAME)
+	DO WHILE (IER.EQ.0)
+	   READ (17,'(Q,A)',IOSTAT=IER) OLEN,OLD_BUFFER
+	   IF (IER.EQ.0.AND.STREQ(FOLDER_NAME(:FLEN)//':',
+     &		OLD_BUFFER(:MIN(FLEN+1,OLEN)))) THEN
+	      BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+	      CALL LOWERCASE(OLD_BUFFER)
+	      IF (INDEX(OLD_BUFFER(FLEN+2:),'defaults')
+     &		.EQ.1) THEN
+		 IF (INDEX(OLD_BUFFER,':header').GT.0)
+     &		            BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,2)
+		 IF (INDEX(OLD_BUFFER,':kill').GT.0)
+     &		            BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,3)
+              ELSE
+	         BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+		 CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC,BLIMIT,BDATE,IER1)
+		 OLD_FORMAT = OLD_FORMAT.OR.(.NOT.IER1)
+		 IF (COMPARE_DATE(OLD_BUFFER(BDATE:OLEN-1),' ').GT.-EXC
+     &		     .OR.EXC.EQ.0) THEN
+	            CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,OLD_BUFFER)
+	            NINCLUDE = NINCLUDE + 1
+		 ELSE
+		    EXC_CHANGED = .TRUE.
+		 END IF
+	      END IF
+	   ELSE IF (IER.EQ.0.AND.OLD_BUFFER(:1).EQ.':') THEN
+	      IF (INDEX(OLD_BUFFER,':header').GT.0)
+     &	                 BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,2)
+	      IF (INDEX(OLD_BUFFER,':kill').GT.0)
+     &	                 BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,3)
+	      IF (INDEX(OLD_BUFFER,':file_directory').GT.0)
+     &	                 FILE_DIRECTORY = OLD_BUFFER(17:)
+	      IF (INDEX(OLD_BUFFER,':exclude_limit').GT.0) THEN 
+	         DECODE(OLEN-15,'(I<OLEN-15>)',OLD_BUFFER(16:),IOSTAT=IER1)
+     &	                EXCLUDE_LIMIT
+	         EXCLUDE_LIMIT = MIN(999,EXCLUDE_LIMIT)
+	      END IF
+	   END IF
+	END DO
+
+	CLOSE (UNIT=17)
+	
+	IF (OLD_FORMAT) CALL CHECK_EXCLUDES
+
+        RETURN
+	END
+
+
+
+	
+	LOGICAL FUNCTION INCLUDE_MSG(STRING,STRING1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /DIRMODE/ DIRMODE
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+
+	CHARACTER*(*) STRING,STRING1
+	CHARACTER*132 ADDRESS
+
+	CHARACTER*12 EXFROM
+
+	INCLUDE_MSG = .TRUE.
+	IF (BTEST(BULL_USER_CUSTOM,4)) RETURN
+	IF (.NOT.BTEST(BULL_USER_CUSTOM,1)) RETURN
+
+	MATCH_FROM = .FALSE.
+	SYSTEM = IBCLR(SYSTEM,8)
+
+	IF (STRING.EQ.'>') THEN 
+	   INCLUDE_MSG = .FALSE.
+	   SYSTEM = IBCLR(SYSTEM,8)
+	   RETURN
+	END IF
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+
+	FLEN = TRIM(FOLDER_NAME)
+
+	DO I=1,NINCLUDE
+	   OLD_SCRATCH_B = SCRATCH_B
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,OLD_BUFFER)
+	   OLEN = TRIM(OLD_BUFFER)
+	   CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC,BLIMIT,BDATE,IER1)
+	   IF (DIRMODE) BLIMIT = MIN(BLIMIT,FLEN+17+LEN(DESCRIP))
+	   MATCH = .FALSE.
+	   IF (STREQ(OLD_BUFFER(FLEN+10:FLEN+14),'FROM:')) THEN
+	      CALL GET_FROM(EXFROM,OLD_BUFFER(FLEN+15:),
+     &			    TRIM(OLD_BUFFER(FLEN+15:)))
+	      IF (STREQ(ADDRESS(STRING),ADDRESS(OLD_BUFFER(FLEN+15:
+     &		  TRIM(OLD_BUFFER(FLEN+15:BLIMIT))+FLEN+14))).OR.
+     &		  (DIRMODE.AND.STREQ(FROM,EXFROM))) THEN
+		 MATCH = .TRUE.
+		 MATCH_FROM = .TRUE.
+	      END IF
+	   ELSE IF (STREQ(OLD_BUFFER(FLEN+10:FLEN+17),'SUBJECT:').AND.
+     &	       STRFIND(STRING1(:TRIM(STRING1)),
+     &		       OLD_BUFFER(FLEN+18:BLIMIT)).GT.0) THEN
+	      MATCH = .TRUE.
+	   END IF
+	   IF (MATCH) THEN
+	      CDATE = COMPARE_DATE(OLD_BUFFER(BDATE:OLEN-1),' ')
+	      IF (CDATE.NE.0.AND.EXC.NE.0) THEN
+		 IF (OLD_BUFFER(BLIMIT+1:BLIMIT+1).EQ.':') EXC = -1
+		 CALL ADD_EXCL(OLD_BUFFER,BLIMIT,EXC)
+		 CALL WRITE_QUEUE(%VAL(OLD_SCRATCH_B),OLD_SCRATCH_B,
+     &			     OLD_BUFFER)
+		 EXC_CHANGED = .TRUE.
+	      END IF
+	      IF (STREQ(OLD_BUFFER(FLEN+2:FLEN+8),'INCLUDE')) THEN
+		 SYSTEM = IBSET(SYSTEM,8)
+		 INCLUDE_MSG = .TRUE.
+	      ELSE IF (.NOT.BTEST(SYSTEM,8).OR.MATCH_FROM) THEN
+C
+C  Only "from" matches override threads, but not subject matches.
+C
+		 INCLUDE_MSG = .FALSE.
+		 SYSTEM = IBCLR(SYSTEM,8)
+		 IF (MATCH_FROM) RETURN
+	      END IF
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+	FUNCTION STRFIND(STRING,STRING1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) STRING,STRING1
+
+	L = LEN(STRING1)
+	DO I=0,LEN(STRING)-L
+	   J = 1
+	   DO WHILE (J.LE.L)
+	      DIFF = ABS(ICHAR(STRING(I+J:I+J))-ICHAR(STRING1(J:J)))
+	      IF (DIFF.NE.0.AND.(DIFF.NE.32.OR..NOT.ALPHA(STRING1(J:J))
+     &		  .OR..NOT.ALPHA(STRING(I+J:I+J)))) THEN
+		 J = L + 1
+	      ELSE IF (J.EQ.L) THEN
+		 STRFIND = I + 1
+		 RETURN
+	      ELSE
+	         J = J + 1
+	      END IF
+	   END DO
+	END DO
+
+	STRFIND = 0
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOW_EXCLUDE(TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	IF (.NOT.BTEST(BULL_USER_CUSTOM,1)) THEN
+	   IF (TYPE.EQ.0) WRITE (6,'('' There are no excludes.'')')
+	   IF (TYPE.EQ.1) WRITE (6,'('' There are no threads.'')')
+	   RETURN
+	END IF
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+
+	FLEN = TRIM(FOLDER_NAME)
+
+	FOUND = .FALSE.
+
+	L = 1
+	DO I=1,NINCLUDE
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,OLD_BUFFER)
+	   OLEN = TRIM(OLD_BUFFER)
+	   IF (STREQ(FOLDER_NAME(:FLEN)//':',OLD_BUFFER(:MIN(FLEN+1,OLEN)))
+     &         .AND.((TYPE.EQ.1.AND.STREQ(OLD_BUFFER(FLEN+2:FLEN+8),
+     &	       'INCLUDE')).OR.(TYPE.EQ.0.AND.STREQ(
+     &	       OLD_BUFFER(FLEN+2:FLEN+8),'EXCLUDE')))) THEN
+	      IF (.NOT.FOUND) THEN
+	         IF (TYPE.EQ.0) WRITE (6,'(1X,A,$)') 'Excludes for '
+		 IF (TYPE.EQ.1) WRITE (6,'(1X,A,$)') 'Threads for '
+		 WRITE (6,'(A)') '+'//FOLDER_NAME(:FLEN)//':'
+	         FOUND = .TRUE.
+ 	      END IF
+	      CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC,BLIMIT,BDATE,IER1)
+	      IF (BLIMIT+5-FLEN.GT.PAGE_WIDTH.AND.L+2.GT.PAGE_LENGTH-1) THEN
+	         L = L + 2
+	      ELSE
+		 IF (L.EQ.0) THEN 
+	            WRITE (6,'(''+'',A,$)') OLD_BUFFER(FLEN+10:
+     &		      MIN(BLIMIT,PAGE_WIDTH+FLEN+9))
+		 ELSE
+	            WRITE (6,'(1X,A,$)') OLD_BUFFER(FLEN+10:
+     &		      MIN(BLIMIT,PAGE_WIDTH+FLEN+9))
+		 END IF
+		 IF (OLD_BUFFER(BDATE+1:BDATE+1).EQ.'-')
+     &		     OLD_BUFFER(BDATE:) = ' '//OLD_BUFFER(BDATE:)
+		 OUTLEN = MIN(BLIMIT,PAGE_WIDTH+FLEN+9)-FLEN-9
+		 IF (OUTLEN.GT.PAGE_WIDTH-16) THEN
+		    WRITE (6,'(1X,<PAGE_WIDTH-15>X,A,1X,I3)')
+     &		       OLD_BUFFER(BDATE:INDEX(OLD_BUFFER
+     &		       (BDATE:),':')+BDATE-2),EXC
+		    L = L + 2
+		 ELSE
+		    WRITE (6,'(''+'',<PAGE_WIDTH-15-OUTLEN>X,A,1X,I3)')
+     &		       OLD_BUFFER(BDATE:INDEX(OLD_BUFFER
+     &		       (BDATE:),':')+BDATE-2),EXC
+		    L = L + 1
+		 END IF
+	      END IF
+              IF (PAGING.AND.L.EQ.PAGE_LENGTH-1) THEN
+                 L = 0                        ! Reinitialize screen counter
+	         CALL LIB$PUT_OUTPUT(' ')
+		 CALL GET_INPUT_NOECHO_PROMPT(
+     &				INPUT(:1),'Press key to continue ... ')
+             	 IER = LIB$ERASE_PAGE(1,1)         ! Erase display
+	      END IF
+	   END IF
+	END DO
+
+	IF (.NOT.FOUND) THEN
+	   IF (TYPE.EQ.0) WRITE (6,'(1X,A,$)') 'No excludes found for '
+	   IF (TYPE.EQ.1) WRITE (6,'(1X,A,$)') 'No threads found for '
+	   WRITE (6,'(A)') '+'//FOLDER_NAME(:FLEN)//':'
+	END IF
+
+	RETURN
+	END
+
+
+
+        SUBROUTINE SET_NEWNAME
+
+        IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLUSER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+
+	CHARACTER*12 NEW,OLD
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: No privs to set a new name.'')')
+	   RETURN
+	END IF
+
+	CALL CLI$GET_VALUE('OLDNAME',OLD,LENO)
+	CALL CLI$GET_VALUE('NEWNAME',NEW,LENN)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	TEMP_USER = USERNAME
+        DO WHILE (REC_LOCK(IER))
+	   READ (4,IOSTAT=IER,KEYEQ=OLD) USER_ENTRY
+	END DO 
+
+	IF (IER.EQ.0) THEN
+	   USERNAME = NEW
+           DO WHILE (REC_LOCK(IER))
+	      READ (4,IOSTAT=IER,KEYEQ=NEW)
+	   END DO 
+	   IF (IER.NE.0) THEN
+	      WRITE (4,IOSTAT=IER) USER_ENTRY
+	   ELSE
+	      REWRITE (4,IOSTAT=IER) USER_ENTRY
+	   END IF	
+	END IF	
+
+	USERNAME = TEMP_USER
+        DO WHILE (REC_LOCK(IER1))
+	   READ (4,IOSTAT=IER1,KEYEQ=USERNAME) USER_ENTRY
+	END DO 
+
+	CALL CLOSE_BULLUSER
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Old name not found.'')') 
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLINF_SHARED
+
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=OLD,IOSTAT=IER) OLD,LAST
+	END DO 
+
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=NEW,IOSTAT=IER)
+	END DO 
+	IF (IER.NE.0) THEN
+	   WRITE (9,IOSTAT=IER) NEW,LAST
+	ELSE
+	   REWRITE (9,IOSTAT=IER) NEW,LAST
+	END IF	
+
+	OLD(LENO:LENO) = CHAR(128.OR.ICHAR(OLD(LENO:LENO)))
+	NEW(LENN:LENN) = CHAR(128.OR.ICHAR(NEW(LENN:LENN)))
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=OLD,IOSTAT=IER) OLD,LAST
+	END DO 
+	IF (IER.EQ.0) THEN
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.NE.0) THEN
+	      WRITE (9,IOSTAT=IER) NEW,LAST
+	   ELSE
+	      REWRITE (9,IOSTAT=IER) NEW,LAST
+	   END IF	
+	ELSE
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.EQ.0) DELETE (9)
+	END IF
+	OLD(LENO:LENO) = CHAR(127.AND.ICHAR(OLD(LENO:LENO)))
+	NEW(LENN:LENN) = CHAR(127.AND.ICHAR(NEW(LENN:LENN)))
+
+	OLD(LENO:LENO) = CHAR(128.OR.ICHAR(OLD(LENO:LENO)))
+	IF (LENO.GT.1) THEN
+	   OLD(LENO-1:LENO-1) = CHAR(128.OR.ICHAR(OLD(LENO-1:LENO-1)))
+	ELSE
+	   OLD(2:2) = CHAR(128.OR.ICHAR(OLD(2:2)))
+	END IF
+	NEW(LENN:LENN) = CHAR(128.OR.ICHAR(NEW(LENN:LENN)))
+	IF (LENN.GT.1) THEN
+	   NEW(LENN-1:LENN-1) = CHAR(128.OR.ICHAR(NEW(LENN-1:LENN-1)))
+	ELSE
+	   NEW(2:2) = CHAR(128.OR.ICHAR(NEW(2:2)))
+	END IF
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=OLD,IOSTAT=IER) OLD,LAST
+	END DO 
+	IF (IER.EQ.0) THEN
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.NE.0) THEN
+	      WRITE (9,IOSTAT=IER) NEW,LAST
+	   ELSE
+	      REWRITE (9,IOSTAT=IER) NEW,LAST
+	   END IF	
+	ELSE
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.EQ.0) DELETE (9)
+	END IF
+
+	CALL CLOSE_BULLINF
+
+        RETURN
+        END
+
+
+	SUBROUTINE CHECK_EXCL(BUFFER,L,EXC,BLIMIT,BDATE,IER)
+
+        IMPLICIT INTEGER (A-Z)
+
+	COMMON /EXCLUDE_LIMIT/ EXCLUDE_LIMIT
+
+        CHARACTER*(*) BUFFER
+
+	DIMENSION BTIM(2)
+
+	BLIMIT = L
+	BDATE = L+3
+
+	IER = BUFFER(L:L).EQ.':'
+	IF (IER) THEN
+	   I = LAST_INDEX(BUFFER(:L-1),':')
+	   IF (I.GT.0) THEN
+	      J = LAST_INDEX(BUFFER(:I-1),':')
+	      IF (J.GT.0) THEN
+		 IF (J.LT.I-1) THEN
+		    DECODE(I-J-1,'(I<I-J-1>)',BUFFER(J+1:I-1),IOSTAT=IER) EXC
+		    IER = IER.EQ.0
+		 ELSE
+		    EXC = EXCLUDE_LIMIT
+		 END IF
+		 IF (IER) BLIMIT = J - 1
+		 CALL STR$UPCASE(BUFFER(I+1:L-1),BUFFER(I+1:L-1))
+		 IF (IER) IER = SYS_BINTIM(BUFFER(I+1:L-1),BTIM)
+		 BDATE = I + 1
+	      END IF
+	   ELSE
+	      IER = .FALSE.
+	   END IF
+	END IF
+
+	IF (.NOT.IER) CALL ADD_EXCL(BUFFER,L,-1)
+
+	RETURN
+	END	
+
+
+
+	SUBROUTINE ADD_EXCL(BUFFER,L,EXC)
+
+        IMPLICIT INTEGER (A-Z)
+
+	DIMENSION BTIM(2)
+
+        CHARACTER*(*) BUFFER
+	
+	CHARACTER TODAY*24
+
+	IF (EXC.EQ.-1) THEN
+	   BUFFER = BUFFER(:L)//':'
+	ELSE
+	   BUFFER = BUFFER(:L)//':'
+	   WRITE (BUFFER(L+2:),'(I3)') EXC
+	   IF (BUFFER(L+2:L+2).EQ. ' ') BUFFER(L+2:) = BUFFER(L+3:)
+	   IF (BUFFER(L+2:L+2).EQ. ' ') BUFFER(L+2:) = BUFFER(L+3:)
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	IF (TODAY(1:1).EQ.' ') TODAY = TODAY(2:)
+	BUFFER = BUFFER(:TRIM(BUFFER))//':'//TODAY(:INDEX(TODAY,' ')-1)//':'
+
+	L = TRIM(BUFFER)
+
+	RETURN
+	END	
+
+
+
+
+	CHARACTER*(*) FUNCTION ADDRESS(INPUT)
+
+	IMPLICIT INTEGER (A - Z)
+
+	CHARACTER*(*) INPUT
+
+	ADDRESS = INPUT
+
+	IF (INDEX(INPUT,'@').EQ.0) RETURN
+
+	I = INDEX(INPUT,'<')
+	IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN ! Name may be of form
+	   ADDRESS = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+						! personal-name <net-name>
+	ELSE
+	   ADDRESS = INPUT(:MINGT0(TRIM(INPUT),INDEX(INPUT,' ')-1))
+	   IF (INDEX(ADDRESS,'(').GT.0)
+     &	       ADDRESS = ADDRESS(:INDEX(ADDRESS,'(')-1)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SEND_MAIL
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER CRLF = CHAR(13)//CHAR(10)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	C = 0
+	DO WHILE (LIB$FIND_FILE(FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &			//'*.SMTP',INPUT,C))
+	   OPEN (UNIT=8,FILE=INPUT(:TRIM(INPUT)),IOSTAT=IER,RECL=256)
+	   IF (IER.NE.0) GOTO 30
+	   IF (.NOT.SMTP_CONNECT()) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'220') GOTO 10
+	   DO I=1,3
+	      READ (8,'(Q,A)',IOSTAT=IER) L,INPUT
+	      IF (IER.NE.0) GOTO 10
+	      IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) GOTO 10
+	      IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	      IF (INPUT(:3).NE.'250') GOTO 10
+	   END DO
+	   READ (8,'(Q,A)',IOSTAT=IER) L,INPUT
+	   IF (IER.NE.0) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'354') GOTO 10
+	   DO WHILE (IER.EQ.0)
+	      READ (8,'(Q,A)',IOSTAT=IER) L,INPUT
+	      IF (IER.EQ.0) THEN
+	         IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) GOTO 10
+	      END IF
+	   END DO
+	   IF (.NOT.SMTP_WRITE_PACKET('.'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('QUIT'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   CLOSE (UNIT=8,STATUS='DELETE')
+	   GOTO 20
+10	   CLOSE (UNIT=8)
+20	   CALL SMTP_DISCONNECT()
+30	   CONTINUE
+	END DO
+
+	CALL EXIT
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin2.for b/decus/vmslt00a/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..3582b62067669d42f0a641cdfc550b197f88203c
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin2.for
@@ -0,0 +1,2692 @@
+C
+C  BULLETIN2.FOR, Version 11/11/99
+C  Purpose: Contains subroutines for the bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE SET_BBOARD(BBOARD)
+C
+C  SUBROUTINE SET_BBOARD
+C
+C  FUNCTION: Set username for BBOARD for selected folder.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($UAIDEF)'
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER EXPIRE*4,INPUT_BBOARD*12,TODAY*24,RESPONSE*4
+
+	IF (TRIM(BBOARD_DIRECTORY).EQ.0) THEN
+	 WRITE(6,'('' ERROR: System programmer has disabled BBOARD.'')')
+	 RETURN
+	END IF
+
+	IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	   IF (FOLDER_BBOARD(:2).EQ.'::') THEN
+	      WRITE (6,'(
+     &		'' ERROR: Cannot set BBOARD for remote folder.'')')
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   END IF
+
+	   IF (BBOARD) THEN
+	      IER = CLI$GET_VALUE('BB_USERNAME',INPUT_BBOARD,INPUT_LEN)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+		 CALL GET_UAF
+     &		   (INPUT_BBOARD,USERB,GROUPB,ACCOUNTB,FLAGS,IER1)
+		 CALL CLOSE_BULLFOLDER
+	         IF (IER1.AND..NOT.BTEST(FLAGS,UAI$V_DISACNT)) THEN ! DISUSER?
+	            WRITE (6,'('' ERROR: '',A,
+     &			'' account needs DISUSER flag set.'')')
+     &			INPUT_BBOARD(:INPUT_LEN)
+		    RETURN
+		 ELSE IF (IER1.AND.BTEST(USERB,31)) THEN
+		    WRITE (6,'('' ERROR: User number of UIC cannot '',
+     &				''be greater than 7777777777.'')')
+		    RETURN
+		 END IF
+		 CALL OPEN_BULLFOLDER
+		 CALL READ_FOLDER_FILE_TEMP(IER)
+		 DO WHILE ((FOLDER1_BBOARD.NE.INPUT_BBOARD.OR.
+     &		     FOLDER1_NUMBER.EQ.FOLDER_NUMBER).AND.IER.EQ.0)
+		   CALL READ_FOLDER_FILE_TEMP(IER)
+	         END DO
+		 IF (FOLDER1_BBOARD.EQ.INPUT_BBOARD.AND.
+     &		      FOLDER1_NUMBER.NE.FOLDER_NUMBER) THEN
+		    WRITE (6,'('' WARNING: Account used by other folder.'',
+     &		     '' If you specify the same account,'')')
+		    WRITE (6,'('' you must specify the address'',
+     &		     '' of the mailing list in the folder description.'')')
+		    CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &                 'Do you still want to make this change? ')
+		    IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+		       CALL CLOSE_BULLFOLDER
+		       WRITE (6,'('' Folder was not modified.'')')
+		       RETURN
+		    END IF
+		 END IF
+		 IF (.NOT.IER1) THEN
+		    CALL CLOSE_BULLFOLDER
+		    WRITE (6,'('' WARNING: '',A,'' account not in SYSUAF'',
+     &		       '' file.'')') INPUT_BBOARD(:INPUT_LEN)
+		    CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &                 'Is the name a mail forwarding entry? '//
+     &		       '(Y/N with N as default): ')
+		    IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+		       WRITE (6,'('' Folder was not modified.'')')
+		       RETURN
+		    END IF
+		    CALL OPEN_BULLFOLDER
+		    USERB = 1		! Fake userb/groupb, as old method of
+		    GROUPB = 1		! indicating /SPECIAL used [0,0]
+		 END IF
+		 GROUPB1 = GROUPB
+		 USERB1 = USERB
+		 ACCOUNTB1 = ACCOUNTB
+		 CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+		 GROUPB = GROUPB1
+		 USERB = USERB1
+		 ACCOUNTB = ACCOUNTB1
+		 FOLDER_BBOARD = INPUT_BBOARD
+		 CALL OPEN_BULLUSER
+		 CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+		 CALL READ_USER_FILE_HEADER(IER)
+		 CALL SYS_BINTIM(TODAY,BBOARD_BTIM)
+		 REWRITE (4) USER_HEADER
+		 CALL CLOSE_BULLUSER
+		 IF (CLI$PRESENT('SPECIAL')) THEN	! SPECIAL specified?
+		    USERB = IBSET(USERB,31)	! Set bit to show /SPECIAL
+		    IF (CLI$PRESENT('VMSMAIL')) THEN
+		       GROUPB = IBSET(GROUPB,31)   ! Set bit to show /VMSMAIL
+		    END IF
+		 END IF
+	      ELSE IF (CLI$PRESENT('SPECIAL')) THEN
+	         USERB = IBSET(0,31)		! Set top bit to show /SPECIAL
+	         GROUPB = 0
+	         DO I=1,LEN(FOLDER_BBOARD)
+		    FOLDER_BBOARD(I:I) = ' '
+	         END DO
+	      ELSE IF (FOLDER_BBOARD(:4).EQ.'NONE') THEN
+	         WRITE (6,'('' ERROR: No BBOARD specified for folder.'')')
+	      END IF
+
+	      IER = CLI$GET_VALUE('EXPIRATION',EXPIRE,EX_LEN)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+	         IF (EX_LEN.GT.3) EX_LEN = 3
+	         READ (EXPIRE,'(I<EX_LEN>)') TEMP
+		 IF (TEMP.GT.BBEXPIRE_LIMIT.AND..NOT.SETPRV_PRIV()) THEN
+		    WRITE (6,'('' ERROR: Expiration cannot be > '',
+     &			I3,'' days.'')') BBEXPIRE_LIMIT
+		    CALL CLOSE_BULLFOLDER
+		    RETURN
+		 ELSE IF (TEMP.LE.0) THEN
+		    WRITE (6,'('' ERROR: Expiration must be > 0.'')')
+		    CALL CLOSE_BULLFOLDER
+		    RETURN
+		 ELSE
+		    FOLDER_BBEXPIRE = TEMP
+		 END IF
+	      ELSE IF (.NOT.CLI$PRESENT('EXPIRATION')) THEN
+		 FOLDER_BBEXPIRE = -1
+	      END IF
+	   ELSE
+	      FOLDER_BBOARD = 'NONE'
+	   END IF
+
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLFOLDER
+	   WRITE (6,'('' BBOARD has been modified for folder.'')')
+	ELSE
+	   WRITE (6,'('' You are not authorized to modify BBOARD.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+
+	SUBROUTINE SET_SYSTEM(SYSTEM_SET)
+C
+C  SUBROUTINE SET_SYSTEM
+C
+C  FUNCTION: Set SYSTEM specification for selected folder.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (FOLDER_NUMBER.LT.0.OR.FOLDER_NUMBER.GE.1000) THEN
+	   WRITE (6,'('' ERROR: Cannot modify for remote folder.'')')
+	ELSE IF (SETPRV_PRIV()) THEN
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   IF (SYSTEM_SET) THEN
+	      FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	      WRITE (6,'('' SYSTEM designation has been set.'')')
+	   ELSE
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,2)
+	      WRITE (6,'('' SYSTEM designation has been removed.'')')
+	   END IF
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL MODIFY_SYSTEM_LIST(0)
+	   CALL CLOSE_BULLFOLDER
+	   CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	ELSE
+	   WRITE (6,'('' You are not authorized to modify SYSTEM.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE MODIFY_SYSTEM_LIST(FILE_OPENED)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	INTEGER SHUTDOWN_BTIM(FLONG),VERSION(FLONG)
+
+	CHARACTER UPDATE*12,UPTIME*8
+
+	INTEGER UP_BTIM(2)
+
+	IF (.NOT.FILE_OPENED) CALL OPEN_BULLUSER
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*SYSTEM',IOSTAT=IER) 
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,VERSION,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END DO
+
+	IF (IER.NE.0.OR.VERSION(1).NE.168) THEN
+	   DO I=1,FLONG
+	      SYSTEM_FLAG(I) = 0
+	      SHUTDOWN_FLAG(I) = 0
+	   END DO
+	   CALL SET2(SYSTEM_FLAG,0)
+	   CALL LIB$SYS_TRNLOG('SYS$NODE',,NODENAME)
+	   NODENAME = NODENAME(2:INDEX(NODENAME,':')-1)
+	   SHUTDOWN_BTIM(1) = 0
+	   SHUTDOWN_BTIM(2) = 0
+	   NODE_NUMBER = 0
+	   NODE_AREA = 0
+	   IF (IER.EQ.0) THEN
+	      DO WHILE (TEMP_USER(:7).EQ.'*SYSTEM'.AND.IER.EQ.0)
+	         DELETE (UNIT=4)
+	         DO WHILE (REC_LOCK(IER))
+	           READ (4,IOSTAT=IER) TEMP_USER
+		 END DO
+	      END DO
+	      IER = 2
+	   ELSE
+	      VERSION(1) = 168
+	   END IF
+	END IF
+
+	IF (VERSION(1).NE.168) THEN
+	   CALL CLOSE_BULLFOLDER
+	   CALL OPEN_BULLFOLDER
+	   NODE_AREA = 0
+	   DO I=1,FLONG
+	      SYSTEM_FLAG(I) = 0
+	   END DO
+	   IER1 = 0
+	   DO WHILE (IER1.EQ.0)
+	      CALL READ_FOLDER_FILE_TEMP(IER1)
+	      IF (BTEST(FOLDER1_FLAG,2).AND.IER1.EQ.0) THEN
+		 CALL SET2(SYSTEM_FLAG,FOLDER1_NUMBER)
+	      END IF
+	   END DO
+	   VERSION(1) = 168
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,2)) THEN
+	   CALL SET2(SYSTEM_FLAG,FOLDER_NUMBER)
+	ELSE
+	   CALL CLR2(SYSTEM_FLAG,FOLDER_NUMBER)
+	END IF
+
+	CALL SYS_BINTIM('-',UP_BTIM)	! Get today's date
+	DIFF = COMPARE_BTIM(SHUTDOWN_BTIM,UP_BTIM)
+	IF (DIFF.GE.0) THEN	! Must have been in a time wrap
+	   SHUTDOWN_BTIM(1) = UP_BTIM(1)
+	   SHUTDOWN_BTIM(2) = UP_BTIM(2)
+	END IF
+
+	CALL GET_UPTIME(UPDATE,UPTIME)
+
+	CALL SYS_BINTIM(UPDATE//' '//UPTIME,UP_BTIM)
+
+	IF (NODE_AREA.EQ.0) THEN
+	   IF (SHUTDOWN_BTIM(1).EQ.0) THEN
+	      DIFF = -1
+	   ELSE
+	      DIFF = COMPARE_BTIM(SHUTDOWN_BTIM,UP_BTIM)
+	   END IF
+	   IF (DIFF.EQ.-1) THEN
+	      CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	      SHUTDOWN_BTIM(1) = UP_BTIM(1)
+	      SHUTDOWN_BTIM(2) = UP_BTIM(2)
+	      DO I=1,FLONG
+		 SHUTDOWN_FLAG(I) = SYSTEM_FLAG(I)
+              END DO
+	   END IF
+	ELSE			! Test to make sure NODE_AREA is zero
+	   SEEN_FLAG = 0		! if all of SHUTDOWN_FLAG is zero
+	   DO I=1,FLONG
+	      IF (SHUTDOWN_FLAG(I).NE.0) SEEN_FLAG = 1
+	   END DO
+	   IF (SEEN_FLAG.EQ.0) NODE_AREA = 0
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (4,IOSTAT=IER)
+     &		'*SYSTEM     ',NODENAME,NODE_NUMBER,NODE_AREA,VERSION,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	ELSE
+	   REWRITE (4,IOSTAT=IER)
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,VERSION,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END IF
+
+	CALL READ_PERM
+
+	IF (.NOT.FILE_OPENED) THEN
+	   CALL CLOSE_BULLUSER
+	   IF (REMOTE_SET) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER1) 14,
+     &				BTEST(FOLDER_FLAG,2),NODENAME
+	      IF (IER1.NE.0) THEN
+	         CALL DISCONNECT_REMOTE
+	         IF (.NOT.FILE_OPENED) CALL CLOSE_BULLUSER
+	         RETURN
+	      END IF
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+	
+	SUBROUTINE GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,SYI$_NODE_AREA,%LOC(NODE_AREA))
+	CALL ADD_2_ITMLST(4,SYI$_NODE_NUMBER,%LOC(NODE_NUMBER))
+	CALL END_ITMLST(GETSYI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETSYIW(,,,%VAL(GETSYI_ITMLST),,,)	! Get Info command.
+C
+C  NODE_AREA is set to 0 after shutdown messages are deleted.
+C  If node is not part of cluster, NODE_AREA will be 0,
+C  so set it to 1 as a dummy value to cause messages to be deleted.
+C
+	IF (NODE_AREA.EQ.0) NODE_AREA = 1
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_NODE(NODE_SET)
+C
+C  SUBROUTINE SET_NODE
+C
+C  FUNCTION: Set or reset remote node specification for selected folder.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER RESPONSE*4,FOLDER_SAVE*44
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (CLI$PRESENT('FOLDER')) THEN
+	   IER = CLI$GET_VALUE('FOLDER',FOLDER1) ! Get folder name
+	   FOLDER_SAVE = FOLDER
+	   CALL OPEN_BULLFOLDER_SHARED		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER1,IER)
+	   IF (IER.EQ.0) THEN
+	      IF (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+		 WRITE (6,'('' ERROR: No privs to modify folder.'')')
+		 IER = 1
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: Specified folder not found.'')')
+	   END IF
+	   IF (IER.NE.0) THEN
+	      CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER)
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   END IF
+	   CALL CLOSE_BULLFOLDER
+	END IF
+
+	IF (FOLDER_NUMBER.EQ.0) THEN
+	   WRITE (6,'('' Cannot set remote node for the default folder.'')')
+	ELSE IF (FOLDER_NUMBER.LT.0.OR.FOLDER_NUMBER.GE.1000) THEN
+	   WRITE (6,'('' Cannot set remote node for this folder.'')')
+	ELSE IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   IF (.NOT.NODE_SET) THEN
+	      IF (INDEX(FOLDER_BBOARD,'*').GT.0) THEN
+		 REMOTE_SET_SAVE = REMOTE_SET
+		 REMOTE_SET = .FALSE.
+	         FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		     FOLDER
+	         CALL OPEN_BULLDIR		! Remove directory file which
+	         CALL CLOSE_BULLDIR_DELETE	! contains remote folder name
+		 REMOTE_SET = REMOTE_SET_SAVE
+	      END IF
+	      FOLDER1_BBOARD = 'NONE'
+	      WRITE (6,'('' Remote node setting has been removed.'')')
+	      IF (.NOT.CLI$PRESENT('FOLDER')) REMOTE_SET = .FALSE.
+	   ELSE
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &          'Are you sure you want to make folder '//
+     &	        FOLDER(:TRIM(FOLDER))//
+     &		' remote? (Y/N with N as default): ')
+	      IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+	        WRITE (6,'('' Folder was not modified.'')')
+	        RETURN
+	      END IF
+	      IF (.NOT.CLI$GET_VALUE('REMOTENAME',FOLDER1)) THEN
+	         FOLDER1 = FOLDER
+	      END IF
+	      IER = CLI$GET_VALUE('NODENAME',FOLDER1_BBOARD,FLEN)
+	      FOLDER1_BBOARD = '::'//FOLDER1_BBOARD(:FLEN)
+	      CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      IF (IER.NE.0) THEN
+	         WRITE (6,'(
+     &		  '' ERROR: Folder not accessible on remote node.'')')
+	         RETURN
+	      ELSE
+	         WRITE (6,'('' Folder has been converted to remote.'')')
+	      END IF
+	      FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		FOLDER
+	      REMOTE_SET_SAVE = REMOTE_SET
+	      REMOTE_SET = .FALSE.
+	      CALL OPEN_BULLDIR			! Remove directory file
+	      CALL OPEN_BULLFIL			! Remove bulletin file
+	      CALL CLOSE_BULLFIL_DELETE
+	      CALL CLOSE_BULLDIR_DELETE
+	      IF (FOLDER.NE.FOLDER1) THEN	! Different remote folder name?
+	         CALL OPEN_BULLDIR		! If so, put name in header
+		 BULLDIR_HEADER(13:) = FOLDER1	! of directory file.
+		 CALL WRITEDIR_NOCONV(0,IER)
+	         CALL CLOSE_BULLDIR
+	         FOLDER1_BBOARD = FOLDER1_BBOARD(:FLEN+2)//'*'
+	      END IF
+	      REMOTE_SET = REMOTE_SET_SAVE
+	      IF (.NOT.CLI$PRESENT('FOLDER')) REMOTE_SET = .TRUE.
+	   END IF
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   IF (.NOT.NODE_SET.AND.FOLDER_BBOARD(:2).EQ.'::'
+     &			.AND.BTEST(FOLDER_FLAG,2)) THEN
+	      OPEN (UNIT=17,STATUS='UNKNOWN',IOSTAT=IER,
+     &		RECL=256,FILE=FOLDER_BBOARD(3:TRIM(FOLDER_BBOARD))
+     &		//'::"TASK=BULLETIN1"')
+	      IF (IER.EQ.0) THEN	! Disregister remote SYSTEM folder
+		 WRITE(17,'(2A)',IOSTAT=IER) 14,0
+		 CLOSE (UNIT=17)
+	      END IF
+	   END IF
+	   FOLDER_BBOARD = FOLDER1_BBOARD
+	   IF (NODE_SET) THEN
+	      F_NBULL = F1_NBULL
+	      F_NEWEST_BTIM(1) = F1_NEWEST_BTIM(1)
+	      F_NEWEST_BTIM(2) = F1_NEWEST_BTIM(2)
+	      F_NEWEST_NOSYS_BTIM(1) = F1_NEWEST_NOSYS_BTIM(1)
+	      F_NEWEST_NOSYS_BTIM(2) = F1_NEWEST_NOSYS_BTIM(2)
+	      FOLDER_FLAG = 0
+	      F_EXPIRE_LIMIT = F1_EXPIRE_LIMIT
+	   ELSE
+	      F_NBULL = 0
+	   END IF
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLFOLDER
+	ELSE
+	   WRITE (6,'('' You are not authorized to modify NODE.'')')
+	END IF
+
+	IF (CLI$PRESENT('FOLDER')) THEN
+	   CALL OPEN_BULLFOLDER_SHARED		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER)
+	   CALL CLOSE_BULLFOLDER
+	   FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		FOLDER
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE RESPOND
+C
+C  SUBROUTINE RESPOND
+C
+C  FUNCTION: Sends a mail message in reply to a posted message.
+C
+C  NOTE: Modify the last SPAWN statement to specify the command
+C	you use to send mail to sites other than via MAIL.
+C	If you always use a different command, modify both
+C	spawn commands.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	COMMON /INDESCRIP/ INDESCRIP
+	CHARACTER*(INPUT_LENGTH) INDESCRIP
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	CHARACTER INFROM*(INPUT_LENGTH)
+
+	EXTERNAL CLI$_NEGATED,CLI$_ABSENT
+
+	MSG_OWN = .FALSE.
+
+	IF (INCMD(:4).EQ.'REPL') THEN
+	   IF (REMOTE_SET.GE.3) THEN
+              BULL_PARAMETER = 'news group.'
+           ELSE
+              BULL_PARAMETER = 'mailing list.'
+           END IF
+	   IF (CLI$PRESENT('ALL')) THEN
+	      IF (REMOTE_SET.GE.3) THEN
+                 BULL_PARAMETER = 'message owner and news group.'
+              ELSE
+                 BULL_PARAMETER = 'message owner and mailing list.'
+              END IF
+	      MSG_OWN = .TRUE.
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'RESP') THEN
+	   MSG_OWN = .TRUE.
+	   BULL_PARAMETER = 'message owner.'
+	   IF (CLI$PRESENT('LIST')) THEN 
+	      IF (REMOTE_SET.GE.3) THEN 
+	   	 BULL_PARAMETER = 'message owner and news group.'
+	      ELSE
+		 BULL_PARAMETER = 'message owner and mailing list.'
+	      END IF
+
+	   END IF
+	ELSE IF (REMOTE_SET.GE.3) THEN 
+	   BULL_PARAMETER = 'news group.'
+	ELSE
+	   BULL_PARAMETER = 'mailing list.'
+	END IF
+
+	LIST = INDEX(BULL_PARAMETER,'mailing list')
+	IF (NEWS_FEED().AND.LIST.GT.0) THEN
+	   BULL_PARAMETER(LIST:) = 'news group'//
+     &				   BULL_PARAMETER(LIST+LEN('mailing list'):)
+	END IF
+
+	IF (MSG_OWN.AND.BTEST(CAPTIVE(-1),1)) THEN
+           WRITE (6,'('' ERROR: MAIL invalid from DISMAIL account.'')')
+           RETURN
+	END IF
+
+	WRITE (6,'('' Sending message to '',A)')
+     &	   BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+
+	IF (INCMD(:4).NE.'POST') THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	      WRITE(6,'('' ERROR: You have not read any message.'')')
+	      RETURN			! And return
+	   END IF
+
+	   CALL OPEN_BULLDIR_SHARED
+
+	   BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,1)
+	   CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+	   BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+
+	   IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	      WRITE(6,'('' ERROR: Bulletin was not found.'')')
+	      CALL CLOSE_BULLDIR		! If not, then error out
+	      RETURN
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      INDESCRIP = INPUT(7:)
+	   ELSE
+	      INDESCRIP = DESCRIP
+	   END IF
+
+	   CALL CLOSE_BULLFIL
+
+	   CALL CLOSE_BULLDIR
+
+	   IF (STREQ(INDESCRIP(:3),'RE:')) THEN
+	      INDESCRIP = 'Re:'//INDESCRIP(4:)
+	   ELSE
+	      INDESCRIP = 'Re: '//INDESCRIP
+	   END IF
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN 
+	   IF (CLI$PRESENT('EXPIRATION')) THEN
+	      CALL GET_EXPIRED(INPUT,IER)
+	      IF (.NOT.IER) RETURN
+	      EXDATE = INPUT(:11)
+	      EXTIME = INPUT(13:23)
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SUBJECT')) THEN
+	   IER = CLI$GET_VALUE('SUBJECT',INDESCRIP,LENDES)
+	   IF (LENDES.GT.LEN(INDESCRIP)) THEN
+	      WRITE(6,'('' ERROR: Subject length exceeded.'')')
+	      RETURN
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'POST') THEN
+	   WRITE(6,'('' Enter subject of message:'')')
+	   CALL GET_LINE(INDESCRIP,LENDES)
+	   IF (LENDES.LE.0) THEN
+	      WRITE(6,'('' ERROR: No subject specified.'')')
+	      RETURN
+	   END IF
+	ELSE
+	   WRITE (6,'('' Message will have the subject:'')')
+	   WRITE (6,'(1X,A)') INDESCRIP(:MIN(TRIM(INDESCRIP),PAGE_WIDTH))
+	END IF
+
+	IF ((CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.	! If /EDIT specified
+     &      (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))) THEN
+	   EDIT = .TRUE.
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	ELSE
+	   EDIT = .FALSE.
+	END IF
+
+	TEXT = CLI$PRESENT('EXTRACT')
+
+	LIST = CLI$PRESENT('LIST')
+
+	ILEN = 0
+
+	FILESPEC = CLI$GET_VALUE('FILESPEC',INPUT,ILEN)
+	IF (FILESPEC.NE.%LOC(CLI$_ABSENT)) THEN
+	   CALL DISABLE_PRIVS
+	   OPEN (UNIT=4,FILE=INPUT(:ILEN),STATUS='OLD',READONLY,
+     &		 SHARED,IOSTAT=IER,FORM='FORMATTED')
+	   CALL ENABLE_PRIVS
+	   IF (IER.NE.0) THEN
+	      WRITE(6,'('' ERROR: Specified file cannot be opened.'')')
+	      RETURN
+           END IF 
+	END IF
+
+	FOUNDFILE = FILESPEC
+
+	IF (EDIT.AND.(TEXT.OR.FILESPEC)) THEN
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH+2,STATUS='NEW',CARRIAGECONTROL='LIST')
+
+	   IF (IER.NE.0) THEN
+	      CALL ERRSNS(IDUMMY,IER)
+	      CALL SYS_GETMSG(IER)
+	      GO TO 900
+	   END IF
+	ELSE IF (TEXT.AND..NOT.EDIT) THEN
+	   WRITE (6,'('' ERROR: Cannot extract text without /EDIT.'')')
+	   GO TO 900
+	END IF
+
+	LENFRO = 0
+	DO WHILE (CLI$GET_VALUE('CC',INPUT,ILEN)
+     &	    .NE.%LOC(CLI$_ABSENT))		
+	   CALL ADD_PROTOCOL(INPUT,ILEN)
+	   IF (LENFRO.EQ.0) THEN
+	      INFROM = INPUT(:ILEN)//','
+	   ELSE
+	      INFROM = INFROM(:LENFRO)//INPUT(:ILEN)//','
+	   END IF
+	   LENFRO = LENFRO + ILEN + 1
+	END DO
+	IF (LENFRO.GT.0.AND..NOT.MSG_OWN) LENFRO = LENFRO - 1
+
+	IF ((EDIT.AND.TEXT).OR.INCMD(:4).NE.'POST') THEN
+	   CALL OPEN_BULLFIL_SHARED
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (MSG_OWN) THEN
+	         ILEN = TRIM(INPUT) - 6
+	         INFROM = INFROM(:LENFRO)//INPUT(7:)
+		 IF (INDEX(INFROM,' "').GT.INDEX(INFROM,'@')) THEN
+		    I = INDEX(INFROM,' "')
+		    INFROM = INFROM(:I-1)//
+     &			     INFROM(INDEX(INFROM(I+2:),'"')+I+2:)
+		    DO WHILE (INDEX(INFROM,'""').GT.0)
+		       INFROM = INFROM(:INDEX(INFROM,'""'))//
+     &				INFROM(INDEX(INFROM,'""')+2:)
+		    END DO
+	         END IF
+	         CALL ADD_PROTOCOL(INFROM(LENFRO+1:),ILEN)
+	         LENFRO = LENFRO + ILEN
+	      END IF
+	      IF (EDIT.AND.TEXT) THEN
+		 INPUT = INPUT(7:)
+		 IF (INDEX(INPUT,'%"').GT.0) THEN
+		    INPUT = INPUT(INDEX(INPUT,'%"')+2:TRIM(INPUT)-1)
+		 END IF
+	         WRITE (3,'(A)') 'In a previous article, '//
+     &			INPUT(:TRIM(INPUT))//' wrote:'
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE IF (MSG_OWN) THEN
+	      CALL ADD_PROTOCOL(FROM,0)
+	      INFROM = INFROM(:LENFRO)//FROM
+	      LENFRO = TRIM(FROM) + LENFRO
+	   END IF
+
+	   IF (EDIT.AND.TEXT) THEN
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      LEN_P = 0
+	      IF (CLI$PRESENT('INDENT').NE.%LOC(CLI$_NEGATED)) THEN
+	         CALL CLI$GET_VALUE('INDENT',BULL_PARAMETER,LEN_P)
+	      END IF
+	      DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	         IF (LEN_P.EQ.0) THEN
+	            WRITE (3,'(A)') INPUT(:ILEN)
+	         ELSE
+	            WRITE (3,'(A)') BULL_PARAMETER(:LEN_P)//INPUT(:ILEN)
+	         END IF
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END DO
+
+	      IF (FILESPEC) THEN
+		 WRITE (3,'(A)') ' '
+		 IER = 0
+		 DO WHILE (IER.EQ.0)
+		    READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		    IF (IER.EQ.0) WRITE (3,'(A)') INPUT(:ILEN)
+		 END DO
+		 CLOSE (UNIT=4)
+	         FILESPEC = .FALSE.
+	      END IF
+
+	      CLOSE (UNIT=3)			! Bulletin copy completed
+	   END IF
+
+	   CALL CLOSE_BULLFIL
+	END IF
+
+	IF (EDIT.AND.FILESPEC.AND..NOT.TEXT) THEN
+	   IER = 0
+	   ICOUNT = 0
+	   DO WHILE (IER.EQ.0)
+	      READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	      IF (IER.EQ.0) THEN
+		 WRITE (3,'(A)') INPUT(:ILEN)
+		 ICOUNT = ICOUNT + 1
+	      END IF
+	   END DO
+	   CLOSE (UNIT=4)
+	   FILESPEC = .FALSE.
+	   IF (ICOUNT.EQ.0) THEN
+	      CLOSE (UNIT=3,STATUS='DELETE')
+	   ELSE
+	      CLOSE (UNIT=3)
+	   END IF
+	END IF
+
+	IF (LIST.AND.REMOTE_SET.LT.3) THEN
+	   SLIST = INDEX(FOLDER_DESCRIP,'<')
+	   IF (SLIST.GT.0) THEN
+	      IF (.NOT.NEWS_FEED()) THEN
+		 INPUT = FOLDER_DESCRIP(SLIST+1:)
+		 ILEN = INDEX(INPUT,'>') - 1
+		 IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+		 INPUT = INPUT(:ILEN)
+	         CALL ADD_PROTOCOL(INPUT,ILEN)
+	         IF (LENFRO.GT.0.AND.INFROM(LENFRO:LENFRO).NE.',') THEN
+		    INFROM = INFROM(:LENFRO)//','
+		    LENFRO = LENFRO + 1
+		 END IF
+	         INFROM = INFROM(:LENFRO)//INPUT(:ILEN)
+	         LENFRO = LENFRO + ILEN
+	      ELSE
+		 FOLDER1_DESCRIP = 
+     &			FOLDER_DESCRIP(SLIST+1:TRIM(FOLDER_DESCRIP)-1)
+		 IF (FOLDER1_DESCRIP(1:1).EQ.'@') THEN
+		    WRITE(6,'('' ERROR: Multiple newsgroup feed'',
+     &			'' is present.'')')
+		    GO TO 900
+		 END IF
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: No list address'',
+     &			'' found in folder description.'')')
+	      GO TO 900
+	   END IF
+	END IF
+
+	I = 1		! Must change all " to "" in FROM field
+	DO WHILE (I.LE.LENFRO)
+	   IF (INFROM(I:I).EQ.'"') THEN
+	      INFROM = INFROM(:I)//'"'//INFROM(I+1:)
+	      I = I + 1
+	      LENFRO = LENFRO + 1
+	   END IF
+	   I = I + 1
+	END DO
+
+	STATUS = .TRUE.
+
+	IF (EDIT) THEN
+	   CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	   CONTEXT = 0
+	   IER =  LIB$FIND_FILE('SYS$LOGIN:BULL.SCR',INPUT,CONTEXT)
+	   IF (TEXT.OR.FOUNDFILE) THEN
+	      VERSION = INDEX(INPUT,';') + 1
+	      IF (INPUT(VERSION:VERSION).EQ.'1') THEN
+	         CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	      ELSE
+	         IER = 0
+	      END IF
+	   ELSE IF (IER) THEN
+	      IER = 0
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      CALL ADD_SIGNATURE(0,'SYS$LOGIN:BULL.SCR',FOLDER_NAME)
+	      IF ((NEWS_FEED().OR.REMOTE_SET.GE.3).AND.LIST) THEN
+	         CALL NEWS_POST('SYS$LOGIN:BULL.SCR',.FALSE.,IER,
+     &			INDESCRIP)
+		 STATUS = IER.EQ.0
+	         IF (IER.EQ.0) THEN
+		    WRITE (6,'('' Message successfully posted.'')')
+	         END IF
+	      END IF
+	      IF (IER.EQ.0.AND.LENFRO.GT.0) THEN
+	         CALL RESPOND_MAIL('SYS$LOGIN:BULL.SCR',INFROM,
+     &			   INDESCRIP,STATUS)
+	      END IF
+	      INPUT = INDESCRIP
+	      CALL INCLUDE_SUBJECT(0)
+	   END IF
+	ELSE
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	   IF (.NOT.FILESPEC) THEN
+	      WRITE (6,'('' Enter message: End with ctrl-z,'',
+     &			 '' cancel with ctrl-c'')')
+	      ILEN = LINE_LENGTH + 1		! Length of input line
+	      ICOUNT = 0			! Character count counter
+	      DO WHILE (ILEN.GE.0)		! Input until no more input
+	         CALL GET_LINE(INPUT,ILEN)	! Get input line
+	         IF (ILEN.GT.LINE_LENGTH) THEN	! Input line too long
+		    WRITE(6,'('' ERROR: Input line length > '',I,
+     &			   ''.  Reinput:'')') LINE_LENGTH
+	         ELSE IF (ILEN.GE.0) THEN	! If good input line entered
+		    ICOUNT = ICOUNT + ILEN		! Update counter
+		    WRITE(3,'(A)') INPUT(:ILEN)	! Save line in scratch file
+	         END IF
+	      END DO
+	   ELSE
+	      IER = 0
+	      ICOUNT = 0
+	      DO WHILE (IER.EQ.0)
+		 READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		 IF (IER.EQ.0) THEN
+		    ICOUNT = ICOUNT + 1
+		    WRITE (3,'(A)') INPUT(:ILEN)
+		 END IF
+	      END DO
+	      CLOSE (UNIT=4)
+	      FILESPEC = .FALSE.
+	   END IF
+	   IF (ILEN.EQ.-1.OR.ICOUNT.EQ.0) THEN	! CTRL_C or No lines
+	      CLOSE (UNIT=3)
+	      IER = 1
+	   ELSE
+	      CALL ADD_SIGNATURE(3,' ',FOLDER_NAME)
+	      REWIND (UNIT=3)
+	      IF ((NEWS_FEED().OR.REMOTE_SET.GE.3).AND.LIST) THEN
+	         CALL NEWS_POST('SYS$LOGIN:BULL.SCR',.TRUE.,IER,
+     &			   INDESCRIP)
+		 STATUS = IER.EQ.0
+	         IF (IER.EQ.0)  WRITE (6,'('' Message successfully posted.'')')
+	      ELSE
+		 IER = 0
+	      END IF
+	      CLOSE (UNIT=3)
+	      IF (IER.EQ.0.AND.LENFRO.GT.0) THEN
+		 CALL RESPOND_MAIL('SYS$LOGIN:BULL.SCR',INFROM,
+     &			   INDESCRIP,STATUS)
+	      END IF
+	      INPUT = INDESCRIP
+	      CALL INCLUDE_SUBJECT(0)
+	   END IF
+	END IF
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: No message added.'')')
+	   IF (.NOT.STATUS) THEN
+	      CALL GET_INPUT_PROMPT(INPUT,ILEN,'Do you want to'//
+     &		' save message? (Y/N with N as default): ')
+	      IF (STREQ(INPUT(:1),'Y')) THEN
+		 CALL LIB$RENAME_FILE('SYS$LOGIN:BULL.SCR',
+     &				      'SYS$LOGIN:BULL.SAV')
+		 WRITE (6,'(A)') ' Message saved in SYS$LOGIN:BULL.SAV.'
+	      END IF
+	   END IF
+	END IF
+
+900	IF (FILESPEC) CLOSE (UNIT=4)
+	CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_SIGNATURE(FILEUNIT,FILENAME,FOLDER_NAME)
+C
+C  SUBROUTINE ADD_SIGNATURE
+C
+C  FUNCTION: Adds signature to message being mailed/posted.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) FOLDER_NAME
+
+	CHARACTER*128 BULL_SIGNATURE
+	DATA BULL_SIGNATURE /'SYS$LOGIN:BULL_SIGNATURE.TXT'/
+
+	CHARACTER*256 INPUT
+
+	IF (CLI$PRESENT('NOSIGNATURE')) RETURN
+
+	OPEN (UNIT=4,FILE=BULL_SIGNATURE,STATUS='OLD',READONLY,
+     &		 SHARED,IOSTAT=IER,FORM='FORMATTED')
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=4,FILE='BULL_SIGNATURE',STATUS='OLD',READONLY,
+     &		    SHARED,IOSTAT=IER,FORM='FORMATTED')
+	END IF
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=4,FILE='MX_SIGNATURE',STATUS='OLD',READONLY,
+     &		    SHARED,IOSTAT=IER,FORM='FORMATTED')
+	END IF
+
+	IF (IER.NE.0) RETURN
+
+	IF (FILEUNIT.EQ.0) THEN
+	   OPEN (UNIT=3,FILE=FILENAME,STATUS='OLD',ACCESS='APPEND',
+     &		 IOSTAT=IER,FORM='FORMATTED')
+	END IF
+
+	ICOUNT = 0
+	MATCH = .FALSE.
+	DO WHILE (IER.EQ.0)
+	   READ (4,'(A)',IOSTAT=IER) INPUT
+	   ILEN = TRIM(INPUT)
+	   DO WHILE (.NOT.MATCH.AND.STREQ(INPUT(:6),'START ').AND.IER.EQ.0)
+	      MATCH = STREQ(INPUT(7:ILEN),FOLDER_NAME(:TRIM(FOLDER_NAME)))
+	      READ (4,'(A)',IOSTAT=IER) INPUT
+	      ILEN = TRIM(INPUT)
+	      IF (.NOT.MATCH) THEN
+	         DO WHILE (.NOT.STREQ(INPUT(:ILEN),'END').AND.IER.EQ.0)
+		    READ (4,'(A)',IOSTAT=IER) INPUT
+	            ILEN = TRIM(INPUT)
+		 END DO
+		 READ (4,'(A)',IOSTAT=IER) INPUT
+	         ILEN = TRIM(INPUT)
+	      END IF
+	   END DO
+	   IF (IER.EQ.0) THEN
+	      IF (MATCH.AND.STREQ(INPUT(:ILEN),'END')) THEN
+	         MATCH = .FALSE.
+	      ELSE
+	         ICOUNT = ICOUNT + 1
+	         IF (ICOUNT.EQ.1) WRITE (3,'(A)',IOSTAT=IER) ' '
+	         WRITE (3,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	      END IF
+	   END IF
+	END DO
+
+	CLOSE (UNIT=4)
+	IF (FILEUNIT.EQ.0) CLOSE (UNIT=3)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION STREQ(INPUT,INPUT1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,INPUT1
+
+	STREQ = .FALSE.
+
+	IF (LEN(INPUT).NE.LEN(INPUT1)) RETURN
+
+	DO I=1,LEN(INPUT)
+	   DIFF = ABS(ICHAR(INPUT(I:I))-ICHAR(INPUT1(I:I)))
+	   IF (DIFF.NE.0.AND.(DIFF.NE.32.OR..NOT.ALPHA(INPUT(I:I))
+     &		  .OR..NOT.ALPHA(INPUT1(I:I)))) RETURN
+	END DO
+
+	STREQ = .TRUE.
+
+	RETURN
+	END
+
+
+
+
+
+
+	SUBROUTINE RESPOND_MAIL(FILE,SENDTO,SUBJECT,STATUS)
+C
+C  SUBROUTINE RESPOND_MAIL
+C
+C  FUNCTION: Sends mail to address.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /MAIL_INFO/ USE_INFROM
+	DATA USE_INFROM /.FALSE./
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	CHARACTER*(*) FILE,SENDTO,SUBJECT
+
+	CHARACTER MAILER*128,MLDESCRIP*(LINE_LENGTH)
+
+	PRIVS = FILE.NE.'SYS$LOGIN:BULL.SCR'
+
+	MLDESCRIP = SUBJECT
+	LENDES = TRIM(MLDESCRIP)
+	I = 1		! Must change all " to "" in SUBJECT field
+	DO WHILE (I.LE.LENDES)
+	   IF (MLDESCRIP(I:I).EQ.'"') THEN
+	      IF (LENDES.EQ.LINE_LENGTH) THEN
+		 MLDESCRIP(I:I) = '`'
+	      ELSE
+		 MLDESCRIP = MLDESCRIP(:I)//'"'
+     &				//MLDESCRIP(I+1:)
+		 I = I + 1
+		 LENDES = LENDES + 1
+	      END IF
+	   END IF
+	   I = I + 1
+	END DO
+
+	LISTSERV = INDEX(FOLDER_DESCRIP,'LISTSERV').GT.0
+	VMSSERV = INDEX(FOLDER_DESCRIP,'VMSSERV').GT.0
+
+	IF (LISTSERV.OR.VMSSERV) CALL SETUSER(FOLDER_BBOARD)
+	IF (PRIVS) CALL DISABLE_PRIVS
+
+	IF (LISTSERV) THEN
+	   IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED')) THEN
+	      IF (.NOT.SYS_TRNLNM('MX_REPLY_TO','DEFINED'))
+     &	         CALL CRELNM('MX_REPLY_TO',USERNAME(:TRIM(USERNAME)))
+	   ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED')) THEN
+	      IF (.NOT.SYS_TRNLNM('PMDF_REPLY_TO','DEFINED'))
+     &	         CALL CRELNM('PMDF_REPLY_TO',USERNAME(:TRIM(USERNAME)))
+	   ELSE
+	      IF (.NOT.SYS_TRNLNM('MULTINET_SMTP_REPLY_TO','DEFINED'))
+     &	         CALL CRELNM('MULTINET_SMTP_REPLY_TO',
+     &		          USERNAME(:TRIM(USERNAME)))
+	   END IF
+	END IF
+
+	IF (USE_INFROM) THEN
+	   IF (INDEX(INFROM,'::').GT.0) THEN
+              IF (LPATH.EQ.0) CALL GET_PATHNAME
+	      IF (LPATH.GT.0) THEN
+		 INFROM = INFROM(INDEX(INFROM,'::')+2:TRIM(INFROM))//
+     &		   	  PATHNAME(:LPATH)
+	      END IF
+	   END IF
+	   IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED')) THEN
+      	      CALL CRELNM('MX_REPLY_TO',INFROM(:TRIM(INFROM)))
+	   ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED')) THEN
+      	      CALL CRELNM('PMDF_REPLY_TO',INFROM(:TRIM(INFROM)))
+	   ELSE
+      	      CALL CRELNM('MULTINET_SMTP_REPLY_TO',INFROM(:TRIM(INFROM)))
+	   END IF
+	END IF
+
+	LEN_SENDTO = TRIM(SENDTO)
+	IF (SYS_TRNLNM('BULL_MAILER',MAILER)) THEN
+	   IF (LISTSERV) THEN
+	      IF (SYS_TRNLNM_SYSTEM('BULL_MAILER',MAILER)) THEN
+	         CALL LIB$SPAWN('@'//MAILER(:TRIM(MAILER))//
+     &		    ' '//FILE(:TRIM(FILE))//' """'//SENDTO(:LEN_SENDTO)
+     &		    //'""" """'//MLDESCRIP(:LENDES)//'""" '
+     &		    //USERNAME(:TRIM(USERNAME)),,,,,,STATUS)
+	      END IF
+	   ELSE
+	      CALL LIB$SPAWN('@'//MAILER(:TRIM(MAILER))//
+     &		 ' '//FILE(:TRIM(FILE))//' """'//SENDTO(:LEN_SENDTO)//
+     &		 '""" """'//MLDESCRIP(:LENDES)//'"""',,,,,,STATUS)
+	   END IF
+	ELSE
+	   I = INDEX(SENDTO,'%""') + 3
+	   DO WHILE (I.LT.LEN_SENDTO-2)
+	      IF (SENDTO(I:I+2).EQ.'"",'.OR.SENDTO(I:I+2).EQ.'%""') THEN
+		 I = I + 3
+	      ELSE IF (SENDTO(I:I+1).EQ.'""') THEN
+		 SENDTO(I:) = ''''//SENDTO(I+2:)
+                 LEN_SENDTO = LEN_SENDTO - 1
+              ELSE IF (SENDTO(I:I).EQ.'\'.AND.
+     &                 SENDTO(I+1:I+1).NE.'\') THEN
+		 SENDTO(I+1:) = '\'//SENDTO(I+1:)
+		 LEN_SENDTO = LEN_SENDTO + 1
+		 I = I + 1
+	      ELSE IF (SENDTO(I:I).EQ.''''.AND.
+     &		       INDEX(SENDTO,'@').GT.I) THEN
+		 SENDTO(I:) = '\s'//SENDTO(I+1:)
+		 LEN_SENDTO = LEN_SENDTO + 1
+		 I = I + 2
+	      END IF
+	      I = I + 1
+	   END DO
+
+           CALL SENDMAIL(FILE(:TRIM(FILE)),SENDTO,
+     &                MLDESCRIP(:LENDES),STATUS)
+           IF (.NOT.STATUS) CALL SYS_GETMSG(STATUS)
+C
+C Use the following if you do not have VMS V5.3 or greater.
+C
+C           CALL LIB$SPAWN('$MAIL SYS$LOGIN:BULL.SCR "'//
+C     &                SENDTO(:LEN_SENDTO)//
+C     &       '" /SUBJECT="'//MLDESCRIP(:LENDES)//'"',,,,,,STATUS)
+	END IF
+
+	IF (PRIVS) CALL ENABLE_PRIVS
+	IF (LISTSERV.OR.VMSSERV) CALL SETUSER(USERNAME)
+	IF (LISTSERV.OR.USE_INFROM) THEN
+	   USE_INFROM = .FALSE.
+	   CALL DELLNM_USER('MULTINET_SMTP_REPLY_TO')
+	   CALL DELLNM_USER('PMDF_REPLY_TO')
+	   CALL DELLNM_USER('MX_REPLY_TO')
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION CONFIRM_USER(USERNAME)
+C
+C  FUNCTION CONFIRM_USER
+C
+C  FUNCTION: Confirms that username is valid user.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) USERNAME
+
+	CALL OPEN_SYSUAF_SHARED
+
+	READ (8,KEY=USERNAME,IOSTAT=CONFIRM_USER)
+
+	CALL CLOSE_SYSUAF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE REPLACE
+C
+C  SUBROUTINE REPLACE
+C
+C  FUNCTION: CHANGE command subroutine.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EDIT/ EDIT_DEFAULT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	CHARACTER INEXDATE*12,INEXTIME*12
+	CHARACTER INDESCRIP*(INPUT_LENGTH),INFROM*(INPUT_LENGTH)
+	CHARACTER*4 ANSWER
+
+	CHARACTER DATE_SAVE*12,TIME_SAVE*12
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	LOGICAL DOALL
+
+	IF (REMOTE_SET.GE.3) THEN
+	   WRITE (6,'('' Cannot CHANGE messages in this folder.'')')
+	   RETURN
+	END IF
+
+C
+C  Get the bulletin number to be replaced.
+C
+
+	ALL = CLI$PRESENT('ALL')
+
+	IER1 = CLI$GET_VALUE('NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER1.EQ.%LOC(CLI$_ABSENT).AND..NOT.ALL) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	      WRITE (6,1005)		! Tell user of the error
+	      RETURN			! and return
+	   END IF
+	   SBULL = BULL_POINT		! Replace the bulletin we are reading
+	   EBULL = SBULL
+
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(BULL_POINT,IER)		! Get message directory entry
+	   CALL CLOSE_BULLDIR
+	   IF (IER.NE.BULL_POINT+1) THEN	! Was message found?
+	      WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      RETURN
+	   END IF
+	ELSE
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(0,IER)		! Get message directory entry
+	   CALL CLOSE_BULLDIR
+	   IF (NBULL.EQ.0) THEN		! Were messages found?
+	      WRITE(6,'('' ERROR: No messages were found.'')')
+	      RETURN
+	   END IF
+
+	   IF (IER1.NE.%LOC(CLI$_ABSENT)) THEN
+	      CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER1)
+	      IF (SBULL.LE.0.OR.IER1.NE.0) THEN
+	         WRITE (6,'(A)') 
+     &		  ' ERROR: Specified message number has incorrect format.'
+	         RETURN
+	      END IF
+	      ALL = .TRUE.
+	   ELSE IF (CLI$PRESENT('ALL')) THEN
+	      SBULL = 1
+	      EBULL = NBULL
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SYSTEM')) THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	    WRITE (6,'(
+     &	     '' ERROR: Not enough privileges to change to system.'')')
+	    RETURN
+	   ELSE IF (.NOT.BTEST(FOLDER_FLAG,2).AND.FOLDER_NUMBER.NE.0) THEN
+	    WRITE (6,'(
+     &       '' ERROR: /SYSTEM cannot be set with selected folder.'')')
+	    RETURN
+	   END IF
+	END IF
+
+	LENFROM = 0
+	IF (CLI$PRESENT('OWNER')) THEN
+	   IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.	! Privileges or
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN				! folder owner?
+	      WRITE(6,1090)		! If not, then error out.
+	      RETURN
+	   ELSE
+	      IER = CLI$GET_VALUE('OWNER',INFROM,LENFROM)
+	      INFROM = 'From: '//INFROM
+	      LENFROM = LENFROM + 6
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SHUTDOWN')) THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	    WRITE (6,'(
+     &	     '' ERROR: Not enough privileges to change to shutdown.'')')
+	    RETURN
+	   ELSE IF (.NOT.BTEST(FOLDER_FLAG,2).AND.FOLDER_NUMBER.NE.0) THEN
+	    WRITE (6,'(
+     &      '' ERROR: /SHUTDOWN cannot be set with selected folder.'')')
+	    RETURN
+	   ELSE IF (CLI$GET_VALUE('SHUTDOWN',BULL_PARAMETER).NE.
+     &		    %LOC(CLI$_ABSENT).AND.REMOTE_SET) THEN
+	    WRITE (6,'('' ERROR: Shutdown node name not'',
+     &			    '' permitted for remote folder.'')')
+	    RETURN
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('PERMANENT').AND.
+     &		F_EXPIRE_LIMIT.GT.0.AND..NOT. ! Expiration limit present
+     &		FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   WRITE (6,'(
+     &	    '' ERROR: Not enough privileges to change to permanent.'')')
+	   RETURN
+	END IF
+C
+C  Check to see if specified bulletin is present, and if the user
+C  is permitted to replace the bulletin.
+C
+
+	CALL OPEN_BULLDIR_SHARED
+
+	SAME_OWNER = .TRUE.
+	DO I=SBULL,EBULL
+	   CALL READDIR(I,IER)	! Get info for specified messages
+	   IF (USERNAME.NE.FROM) SAME_OWNER = .FALSE. 
+	END DO
+	CALL READDIR(SBULL,IER)
+
+	CALL CLOSE_BULLDIR
+
+	IF (.NOT.SAME_OWNER) THEN	! If doesn't match owner of bulletin,
+	   IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.	! Privileges or
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN				! folder owner?
+	      WRITE(6,1090)		! If not, then error out.
+	      RETURN
+	   ELSE
+	      WRITE (6,1100)		! Make sure user wants to delete it
+	      READ (5,'(A)',IOSTAT=IER) ANSWER	! Get his answer
+	      CALL STR$UPCASE(ANSWER,ANSWER)	! Convert input to uppercase
+	      IF (ANSWER(:1).NE.'Y') RETURN	! If not Yes, then exit
+	   END IF
+	END IF
+
+C
+C  If no switches were given, replace the full bulletin
+C
+
+	DOALL = .FALSE.
+
+	IF ((.NOT.CLI$PRESENT('EXPIRATION')).AND.
+     &	   (.NOT.CLI$PRESENT('GENERAL')).AND.
+     &	   (.NOT.CLI$PRESENT('SYSTEM')).AND.
+     &	   (.NOT.CLI$PRESENT('HEADER')).AND.
+     &	   (.NOT.CLI$PRESENT('SUBJECT')).AND.
+     &	   (.NOT.CLI$PRESENT('TEXT')).AND.
+     &	   (.NOT.CLI$PRESENT('OWNER')).AND.
+     &	   (.NOT.CLI$PRESENT('SHUTDOWN')).AND.
+     &	   (.NOT.CLI$PRESENT('PERMANENT'))) THEN
+	   DOALL = .TRUE.
+	END IF
+
+	TEXT = CLI$PRESENT('TEXT').OR.CLI$PRESENT('EDIT')
+
+	IF (SBULL.NE.EBULL.AND.(DOALL.OR.TEXT)) THEN
+	   WRITE (6,'('' ERROR: Cannot change text when replacing'',
+     &		      '' more than one messsage.'')')
+	   RETURN
+	END IF
+
+	CALL DISABLE_CTRL			! Disable CTRL-Y & -C
+
+	PERMANENT = .FALSE.
+	IF (CLI$PRESENT('EXPIRATION').OR.DOALL) THEN
+	   SYSTEM = 0
+	   CALL GET_EXPIRED(INPUT,IER)
+	   PERMANENT = BTEST(SYSTEM,1)
+	   IF (.NOT.IER) GO TO 910
+	   INEXDATE = INPUT(:11)
+	   INEXTIME = INPUT(13:23)
+	END IF
+
+8	LENDES = 0
+	IF (CLI$PRESENT('HEADER').OR.DOALL) THEN
+	   WRITE(6,1050)			! Request header for bulletin
+	   READ(5,'(Q,A)',END=910,ERR=910) LENDES,INDESCRIP
+	   IF (LENDES.EQ.0) GO TO 910		! If no header, don't add bull
+	ELSE IF (CLI$PRESENT('SUBJECT')) THEN
+	   IER = CLI$GET_VALUE('SUBJECT',INDESCRIP,LENDES)
+	END IF
+
+	IF (LENDES.GT.0) THEN
+	   INDESCRIP = 'Subj: '//INDESCRIP
+	   LENDES = MIN(LENDES+6,LEN(INDESCRIP))
+	END IF
+ 
+	IF (SBULL.NE.EBULL) CALL OPEN_BULLDIR
+
+	DO NUMBER=SBULL,EBULL
+	 NUMBER_PARAM = NUMBER
+	 IF (SBULL.NE.EBULL) THEN
+	   CALL READDIR(NUMBER_PARAM,IER)
+	   IF (IER.NE.NUMBER_PARAM+1) THEN	! Couldn't find message
+	      CALL CLOSE_BULLDIR
+	      WRITE(6,'('' ERROR: Message '',I6,'' cannot be found.'')')
+     &			NUMBER_PARAM
+	      WRITE(6,'('' All messages up to that message were modified.'')')
+	      RETURN
+	   END IF
+	 END IF
+
+	 REC1 = 0
+
+	 IF (LENDES.GT.0.OR.TEXT.OR.DOALL.OR.LENFROM.GT.0) THEN
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &	     RECL=LINE_LENGTH,STATUS='SCRATCH',CARRIAGECONTROL='LIST')
+
+	   IF (IER.NE.0) THEN
+	      CALL ERRSNS(IDUMMY,IER)
+	      CALL SYS_GETMSG(IER)
+	      GO TO 910
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED
+
+	   REC1 = 1
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (LENFROM.EQ.0) THEN
+	         INFROM = INPUT(:ILEN)
+	         LENFROM = ILEN
+ 	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      IF (LENDES.EQ.0.AND..NOT.DOALL) THEN
+		 INDESCRIP = INPUT(:ILEN)
+		 LENDES = ILEN
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	      WRITE (3,'(A)') INPUT(:ILEN)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END DO
+
+	   CALL CLOSE_BULLFIL
+
+	   IF (TEXT.OR.DOALL) CLOSE(UNIT=3)
+	 END IF
+
+	 IF (TEXT.OR.DOALL) THEN
+C
+C  If file specified in REPLACE command, read file to obtain bulletin.
+C  Else, read the bulletin from the terminal.
+C
+	
+	  ICOUNT = 0				! Line count for bulletin
+	  LAST_NOBLANK = 0			! Last line with data
+	  REC1 = 1
+
+	  IER = CLI$GET_VALUE('FILESPEC',BULL_PARAMETER,LEN_P)
+	  IF (IER.NE.%LOC(CLI$_ABSENT).OR.	! If file param in ADD command
+     &	    ((CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.	! or /EDIT specified
+     &       (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED)))) THEN
+
+	   IF ((CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND. ! If /EDIT specified
+     &       (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))) THEN
+	      IF (LEN_P.EQ.0) THEN		! If no file param specified
+		 IF (.NOT.CLI$PRESENT('NEW')) THEN
+	            OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='NEW',
+     &		       RECL=LINE_LENGTH,
+     &		       ERR=920,FORM='FORMATTED',CARRIAGECONTROL='LIST')
+	            CALL OPEN_BULLFIL_SHARED	! Prepare to copy message
+		    ILEN = LINE_LENGTH + 1
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END IF
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END IF
+		    DO WHILE (ILEN.GT.0)	! Copy message into file
+		       WRITE (3,'(A)') INPUT(:ILEN)
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END DO
+		    CALL CLOSE_BULLFIL
+	            CLOSE (UNIT=3)		! Bulletin copy completed
+		 END IF
+		 CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	      ELSE 
+	         CALL DISABLE_PRIVS
+		 CALL MAILEDIT(BULL_PARAMETER(:LEN_P),'SYS$LOGIN:BULL.SCR')
+	      END IF
+	      IER = LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;-1')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 DISPOSE='DELETE',ERR=920,FORM='FORMATTED')
+	   ELSE IF (LEN_P.GT.0) THEN
+	      CALL DISABLE_PRIVS
+	      OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED') ! Try opening the file
+	   END IF
+
+	   CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+
+	   DO WHILE(1)				! Read until end of file to
+	      READ (3,'(Q,A)',END=10) ILEN,INPUT	! get record count
+	      IF (ILEN.GT.LINE_LENGTH) GO TO 950
+	      CALL STR$TRIM(INPUT,INPUT,ILEN)
+	      IF (ILEN.GT.0) THEN		! If good input line entered
+		 ICOUNT = ICOUNT + ILEN + 1	! Increment record count
+		 LAST_NOBLANK = ICOUNT
+	      ELSE IF (ILEN.EQ.0) THEN
+		 IF (ICOUNT.GT.0) THEN
+		    ICOUNT = ICOUNT + 2		! COPY_BULL writes a line with
+		 ELSE				! 1 space for a blank line.
+		    REC1 = REC1 + 1
+		 END IF
+	      END IF
+	   END DO
+	  ELSE					! If no input file
+	   OPEN (UNIT=3,STATUS='NEW',FILE='SYS$LOGIN:BULL.SCR',ERR=920,
+     &		 DISPOSE='DELETE',FORM='FORMATTED',RECL=LINE_LENGTH,
+     &		 CARRIAGECONTROL='LIST')	! Scratch file to save bulletin
+	   WRITE (6,1000)		! Request bulletin input from terminal
+	   ILEN = LINE_LENGTH			! Length of input line
+	   DO WHILE (ILEN.GE.0)			! Input until no more input
+	      CALL GET_LINE(INPUT,ILEN)		! Get input line
+	      IF (ILEN.GT.LINE_LENGTH) THEN	! Line too long.
+		 WRITE(6,'('' ERROR: Input line length > '',I,
+     &			''. Reinput::'')') LINE_LENGTH
+	      ELSE IF (ILEN.GT.0) THEN		! If good input line entered
+		 ICOUNT = ICOUNT + 1 + ILEN	! Increment character count
+		 WRITE(3,'(A)') INPUT(:ILEN)	! Save line in scratch file
+		 LAST_NOBLANK = ICOUNT
+	      ELSE IF (ILEN.EQ.0.AND.ICOUNT.GT.0) THEN
+		 WRITE(3,'(A)') INPUT(:ILEN)	! Save line in scratch file
+		 ICOUNT = ICOUNT + 2		! COPY_BULL writes a line with
+	      END IF				! 1 space for a blank line.
+	   END DO
+	   IF (ILEN.EQ.-1) GO TO 910		! CTRL_C entered, error out
+10	   ICOUNT = LAST_NOBLANK
+	   IF (ICOUNT.EQ.0) GO TO 910		! No lines entered, error out
+	  ENDIF
+
+	 END IF
+
+C
+C  Add bulletin to bulletin file and directory entry for to directory file.
+C
+
+	 DATE_SAVE = DATE
+	 TIME_SAVE = TIME
+	 INPUT = DESCRIP
+
+	 IF (SBULL.EQ.EBULL) THEN
+	  CALL OPEN_BULLDIR			! Prepare to add dir entry
+	  CALL READDIR(NUMBER_PARAM,IER)	! Get info for message
+
+	  IF (IER.NE.NUMBER_PARAM+1.OR.DATE.NE.DATE_SAVE.OR.
+     &	     TIME.NE.TIME_SAVE.OR.INPUT.NE.DESCRIP) THEN
+				! If message disappeared, try to find it.
+	   IF (IER.NE.NUMBER_PARAM+1) DATE = ' '
+	   NUMBER_PARAM = 0
+	   IER = 1
+	   DO WHILE (IER.EQ.NUMBER_PARAM+1.AND.
+     &	    (DATE.NE.DATE_SAVE.OR.TIME.NE.TIME_SAVE.OR.DESCRIP.NE.INPUT))
+	      NUMBER_PARAM = NUMBER_PARAM + 1
+	      CALL READDIR(NUMBER_PARAM,IER)
+	   END DO
+
+	   IF (IER.NE.NUMBER_PARAM+1) THEN	! Couldn't find message
+	      CALL CLOSE_BULLDIR
+	      CLOSE (UNIT=3,STATUS='SAVE')
+	      WRITE(6,'('' ERROR: Message has been deleted'',
+     &			'' by another user.'')')
+	      IF (DOALL.OR.TEXT) THEN
+		 WRITE (6,'('' New text has been saved in'',
+     &				'' SYS$LOGIN:BULL.SCR.'')')
+	      END IF
+	      GO TO 100
+	   END IF
+	  END IF
+	 END IF
+
+	 CALL READDIR(0,IER)			! Get directory header
+
+	 IF (REC1.GT.0) THEN			! If text has been replaced
+
+	   CALL OPEN_BULLFIL			! Prepare to add bulletin
+
+	   BLOCK = NBLOCK + 1
+	   BLOCK_SAVE = BLOCK
+	   NEMPTY = NEMPTY + LENGTH
+
+	   OBLOCK = BLOCK
+	   IF (LENFROM.GT.0) THEN
+	      CALL STORE_BULL(LENFROM,INFROM(:LENFROM),OBLOCK)
+	   END IF
+	   IF (LENDES.GT.0) THEN
+	      CALL STORE_BULL(LENDES,INDESCRIP(:LENDES),OBLOCK)
+	   END IF
+	   REWIND (UNIT=3)
+	   CALL COPY_BULL(3,REC1,OBLOCK,IER)	! Add the new bulletin
+	   IF (IER.NE.0) THEN		! Error in creating bulletin
+	      WRITE (6,'(A)') ' ERROR: Unable to replace message.'
+	      CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	      CLOSE (UNIT=3)
+	      GO TO 100
+	   END IF
+
+	   LENGTH_SAVE = OCOUNT - BLOCK + 1
+	   NBLOCK = NBLOCK + LENGTH_SAVE
+
+	   IF (.NOT.REMOTE_SET) CALL WRITEDIR(0,IER)
+
+	   CALL CLOSE_BULLFIL
+
+	   IF (.NOT.REMOTE_SET) THEN
+	    CALL READDIR(NUMBER_PARAM,IER)	! Get directory entry
+	    LENGTH = LENGTH_SAVE		! Update size
+	    BLOCK = BLOCK_SAVE
+	    CALL WRITEDIR(NUMBER_PARAM,IER)	! Write new directory entry
+	   END IF
+	 ELSE
+	   CALL READDIR(NUMBER_PARAM,IER)
+	 END IF
+
+	 IF (.NOT.REMOTE_SET) THEN
+
+	   IF (LENDES.GT.0.OR.DOALL) THEN
+	      DESCRIP=INDESCRIP(7:62)		! Update description header
+	   END IF
+	   CALL UPDATE_DIR_HEADER((CLI$PRESENT('EXPIRATION').OR.DOALL).AND.
+     &		.NOT.PERMANENT,CLI$PRESENT('PERMANENT').OR.PERMANENT,
+     &		CLI$PRESENT('SHUTDOWN'),INEXDATE,INEXTIME)
+	   IF (CLI$PRESENT('SYSTEM')) THEN
+	      SYSTEM = IBSET(SYSTEM,0)
+	   ELSE IF (CLI$PRESENT('GENERAL')) THEN
+	      SYSTEM = IBCLR(SYSTEM,0)
+	   END IF
+	   IF (CLI$PRESENT('OWNER')) THEN
+	      CALL GET_FROM(FROM,INFROM(7:),LENFROM-6)
+	      CALL STR$UPCASE(FROM,FROM)
+	   END IF
+	   CALL WRITEDIR(NUMBER_PARAM,IER)
+	 ELSE
+	   MSGTYPE = 0
+	   IF (CLI$PRESENT('SYSTEM').OR.
+     &		(BTEST(SYSTEM,0).AND..NOT.CLI$PRESENT('GENERAL'))) THEN
+	      MSGTYPE = IBSET(MSGTYPE,0)
+	   END IF
+	   IF (CLI$PRESENT('PERMANENT').OR.PERMANENT) THEN
+	      MSGTYPE = IBSET(MSGTYPE,1)
+	   ELSE IF (CLI$PRESENT('SHUTDOWN')) THEN
+	      MSGTYPE = IBSET(MSGTYPE,2)
+	   ELSE IF ((CLI$PRESENT('EXPIRATION').OR.DOALL)
+     &		    .AND..NOT.PERMANENT) THEN
+	      MSGTYPE = IBSET(MSGTYPE,3)
+	   END IF
+	   IF (LENDES.EQ.0.AND..NOT.DOALL) INDESCRIP(7:) = DESCRIP
+	   IF (CLI$PRESENT('EXPIRATION').OR.DOALL) THEN
+	      EXDATE = INEXDATE
+	      EXTIME = INEXTIME
+	   END IF
+	   WRITE (REMOTE_UNIT,'(7A)',IOSTAT=IER)
+     &      10,DESCRIP,NUMBER_PARAM,INDESCRIP(7:62),MSGTYPE,
+     &	    EXDATE,EXTIME
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (I.NE.LEN(FOLDER1_COM)) THEN
+		 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      END IF
+	   ELSE
+	      CALL DISCONNECT_REMOTE
+	   END IF
+	 END IF
+	END DO
+
+	CALL CLOSE_BULLDIR		! Totally finished with replace
+
+	CLOSE (UNIT=3)
+
+100	CALL ENABLE_CTRL		! Enable CTRL-Y & -C
+	RETURN
+
+910	WRITE(6,1010)
+	CLOSE (UNIT=3,ERR=100)
+	GOTO 100
+
+920	WRITE(6,1020)
+	CALL ENABLE_PRIVS	! Reset SYSPRV privileges
+	GOTO 100
+
+950	WRITE (6,1030) LINE_LENGTH
+	CLOSE (UNIT=3)
+	GO TO 100
+
+1000	FORMAT (' Enter message: End with ctrl-z, cancel with ctrl-c')
+1005	FORMAT (' ERROR: You are not reading any message.')
+1010	FORMAT (' No message was replaced.')
+1015	FORMAT (' ERROR: Specified message was not found.')
+1020	FORMAT (' ERROR: Unable to open specified file.')
+1030	FORMAT (' ERROR: Line length in file exceeds '',I,'' characters.')
+1050	FORMAT (' Enter description header.')
+1090	FORMAT(' ERROR: Specified message is not owned by you.')
+1100	FORMAT(' Message(s) is not owned by you.',
+     &	       ' Are you sure you want to replace it? ',$)
+2020	FORMAT(1X,A)
+
+	END
+
+
+
+	SUBROUTINE UPDATE_DIR_HEADER(EXPIRE,PERM,SHUT,INEXDATE,INEXTIME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	CHARACTER TODAY*24,INEXDATE*12,INEXTIME*12
+
+	IF (EXPIRE) THEN
+	   SYSTEM = IBCLR(SYSTEM,1)
+	   SYSTEM = IBCLR(SYSTEM,2)
+	   EXDATE=INEXDATE			! Update expiration date
+	   EXTIME=INEXTIME
+	   DIFF = COMPARE_DATE(EXDATE,NEWEST_EXDATE)	! Compare expiration
+	   IF (DIFF.EQ.0) DIFF = COMPARE_TIME(EXTIME,NEWEST_EXTIME)
+	   IF (DIFF.LT.0) THEN			! If it's oldest expiration bull
+	      NEWEST_EXDATE = EXDATE		! Update the header in
+	      NEWEST_EXTIME = EXTIME		! the directory file
+	      CALL WRITEDIR(0,IER)
+	   END IF
+	ELSE IF (PERM.AND.(.NOT.BTEST(SYSTEM,1))) THEN
+	   IF (BTEST(SYSTEM,2)) THEN
+	      SYSTEM = IBCLR(SYSTEM,2)
+	      SHUTDOWN = SHUTDOWN - 1
+	      CALL WRITEDIR(0,IER)
+	   END IF
+	   SYSTEM = IBSET(SYSTEM,1)
+	   EXDATE = '5-NOV-2100'
+	   EXTIME = '00:00:00.00'
+	ELSE IF (SHUT.AND.(.NOT.BTEST(SYSTEM,2))) THEN
+	   SYSTEM = IBSET(SYSTEM,2)
+	   SYSTEM = IBCLR(SYSTEM,1)
+	   EXDATE = '5-NOV-2100'
+	   NODE_AREA = 0
+	   IF (INCMD(:4).EQ.'REPL') THEN
+	      IF (CLI$GET_VALUE('SHUTDOWN',NODE_NAME)
+     &		    .NE.%LOC(CLI$_ABSENT)) THEN
+		 CALL GET_NODE_NUMBER_OTHER(NODE_NUMBER,NODE_AREA,NODE_NAME)
+	         IF (NODE_AREA.EQ.0) THEN
+		    WRITE (6,'('' ERROR: Shutdown node name ignored.'',
+     &		               '' Invalid node name specified.'')')
+		 END IF
+	      END IF
+	   END IF
+	   IF (NODE_AREA.EQ.0) CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	   WRITE (EXTIME,'(I4)') NODE_NUMBER
+	   WRITE (EXTIME(7:),'(I4)') NODE_AREA
+	   DO I=1,11
+	      IF (EXTIME(I:I).EQ.' ') EXTIME(I:I) = '0'
+	   END DO
+	   EXTIME = EXTIME(1:2)//':'//EXTIME(3:4)//':'//
+     &		    EXTIME(7:8)//'.'//EXTIME(9:10)
+	   SHUTDOWN = SHUTDOWN + 1
+	   CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	   SHUTDOWN_DATE = TODAY(:11)
+	   SHUTDOWN_TIME = TODAY(13:)
+	   CALL WRITEDIR(0,IER)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SEARCH(READ_COUNT)
+C
+C  SUBROUTINE SEARCH
+C
+C  FUNCTION: Search for bulletin with specified string
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	CHARACTER*132 SEARCH_STRING
+	DIMENSION SEARCH_LEN(10)
+
+        CHARACTER GROUP*80,STAT*4
+
+	EXTERNAL CLI$_ABSENT
+
+	IF (CLI$PRESENT('NOREPLIES')) THEN
+	   SEARCH_STRING = 'RE:'
+	   SEARCH_LEN(1) = 3
+	   SEARCH_NUM = 1
+	   NFOLDER = 1
+	ELSE IF (CLI$PRESENT('REPLY')) THEN
+	   SEARCH_STRING = ' '
+	   SEARCH_NUM = 1
+	   NFOLDER = 1
+	   INPUT = DESCRIP
+	   CALL INCLUDE_SUBJECT(0)
+	ELSE IF (CLI$PRESENT('SEARCH_STRING')) THEN
+	   SEARCH_NUM = 1
+	   J = 1
+	   DO WHILE (CLI$GET_VALUE('SEARCH_STRING',SEARCH_STRING(J:),
+     &	    SEARCH_LEN(SEARCH_NUM)).NE.%LOC(CLI$_ABSENT))
+	      J = J + SEARCH_LEN(SEARCH_NUM)
+	      SEARCH_NUM = SEARCH_NUM + 1
+	   END DO
+           IF (SEARCH_NUM.GT.1) SEARCH_NUM = SEARCH_NUM - 1
+	   NFOLDER = 1
+	ELSE
+	   IF (NFOLDER.EQ.0) NFOLDER = 1
+	   SEARCH_STRING = ' '
+	END IF
+
+	IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	   CALL INIT_QUEUE(SCRATCH_F1,FOLDER1_NAME)
+	   SCRATCH_F = SCRATCH_F1
+	   NFOLDER = 0
+	END IF
+
+	DO WHILE (CLI$GET_VALUE('SELECT_FOLDER',FOLDER1_NAME)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified folders
+	   IF (TRIM(FOLDER1_NAME).EQ.0) FOLDER1_NAME = FOLDER_NAME
+	   NFOLDER = NFOLDER + 1
+	   CALL WRITE_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,FOLDER1_NAME)
+	END DO
+
+	IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	   SCRATCH_F = SCRATCH_F1
+	   NFOLDER = NFOLDER + 1
+	END IF
+
+	IF (CLI$PRESENT('GROUP')) THEN
+	   CALL INIT_QUEUE(SCRATCH_F1,GROUP)
+	   SCRATCH_F = SCRATCH_F1
+	   NFOLDER = 0
+	   NGROUP = 0
+	   DO WHILE (CLI$GET_VALUE('GROUP',GROUP)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified folders
+	      NGROUP = NGROUP + 1
+	      CALL LOWERCASE(GROUP)
+	      CALL WRITE_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	   END DO
+	   SCRATCH_F = SCRATCH_F1
+	   CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	   GLEN = TRIM(GROUP)
+	   FEEDBACK = CLI$PRESENT('FEEDBACK')
+	   NFOLDER = -1000
+	   OLD_BUFFER = ' '
+	END IF
+
+	START_BULL = BULL_POINT
+
+	IF (CLI$PRESENT('START')) THEN		! Starting message specified
+	   IF (CLI$GET_VALUE('START',BULL_PARAMETER,LEN_P)) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) START_BULL
+	   END IF
+	   IF (.NOT.CLI$PRESENT('REPLY')) START_BULL = START_BULL - 1
+	END IF
+
+	MATCH_MODE = 0
+	IF (CLI$PRESENT('MATCH')) THEN 
+	   CALL CLI$GET_VALUE('MATCH',BULL_PARAMETER,LEN_P)
+           IF (BULL_PARAMETER(:LEN_P).EQ.'AND') MATCH_MODE = 1
+           IF (BULL_PARAMETER(:LEN_P).EQ.'XOR') MATCH_MODE = 2
+	END IF
+
+	IF (NFOLDER.NE.0) FOUND = 0
+
+	CHANGE = .FALSE.
+	IF (CLI$PRESENT('REPLY').OR.
+     &	    TRIM(SEARCH_STRING).GT.0) THEN 
+	   REVERSE = CLI$PRESENT('REVERSE')
+	ELSE
+	   REVERSE = .FALSE.
+	END IF
+
+	DO WHILE (NFOLDER.NE.0.AND.FOUND.LE.0.AND.FOUND.GT.-3)
+	   IF ((NFOLDER.GT.0.AND.(.NOT.CLI$PRESENT('SELECT_FOLDER').OR.
+     &	       SCRATCH_F.NE.SCRATCH_F1)).OR.
+     &	       (NFOLDER.LT.0.AND.OLD_BUFFER.NE.' '))
+     &	      CALL GET_SEARCH(FOUND,SEARCH_STRING,SEARCH_NUM,
+     &		SEARCH_LEN,MATCH_MODE,START_BULL,
+     &		REVERSE,CLI$PRESENT('SUBJECT')
+     &	        .OR.CLI$PRESENT('NOREPLIES'),
+     &		CLI$PRESENT('REPLY'),.TRUE.,CLI$PRESENT('START'),
+     &		CLI$PRESENT('FROM'),CLI$PRESENT('NEGATED')
+     &	        .OR.CLI$PRESENT('NOREPLIES'),CHANGE)
+	   IF (FOUND.LE.0.AND.FOUND.GE.-2) THEN
+	      NFOLDER = NFOLDER - 1
+	      IF (NFOLDER.GT.0) THEN
+	         CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,FOLDER1_NAME)
+		 OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	         FOLDER_NUMBER = -1
+		 IER = 0
+		 DO WHILE (.NOT.IER.AND.NFOLDER.GT.0)
+		    FOLDER1 = FOLDER1_NAME
+	            CALL SELECT_FOLDER(.FALSE.,IER)
+		    IF (.NOT.IER) THEN
+		       FOLDER_NUMBER = OLD_FOLDER_NUMBER
+		       WRITE (6,'('' ERROR: Cannot find folder '',A,
+     &			  ''.'')') FOLDER1_NAME(:TRIM(FOLDER1_NAME))
+	               CALL GET_INPUT_PROMPT(FOLDER1_NAME,ILEN,
+     &		       'Type new folder name or hit RETURN to continue: ')
+	               IF (ILEN.LE.0.AND.NFOLDER.GT.0) THEN
+		          NFOLDER = NFOLDER - 1
+	                  CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,
+     &				          FOLDER1_NAME)
+		       END IF
+		    ELSE
+	   	       IF (FEEDBACK) WRITE (6,'('' Searching '',A)')
+     &				FOLDER_NAME(:TRIM(FOLDER_NAME))
+		       CHANGE = .TRUE.
+	      	       START_BULL = 0
+		       IF (REVERSE) START_BULL = NBULL - 1
+		    END IF
+		 END DO
+	      ELSE IF (NFOLDER.LT.0) THEN
+		 NFOLDER = NFOLDER + 1
+		 GFOUND = .FALSE.
+	       	 CALL DECLARE_CTRLC_AST
+		 DO WHILE (.NOT.GFOUND.AND.NGROUP.GT.0.AND.FLAG.NE.1)
+	            CALL OPEN_BULLNEWS_SHARED
+		    CALL READ_FOLDER_FILE_KEYNUM_TEMP(-NFOLDER,IER)
+		    IF (IER.EQ.0) 
+     &		       CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+		    DO WHILE (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10))
+		       CALL READ_FOLDER_FILE_TEMP(IER)
+	            END DO
+		    IF (IER.NE.0) NFOLDER = 0
+		    DO WHILE (.NOT.GFOUND.AND.NFOLDER.NE.0.AND.FLAG.NE.1)
+	               CALL GET_NEXT_GROUP(.TRUE.,GROUP,GLEN,GFOUND,
+     &				        .FALSE.,STAT,IER,.TRUE.)
+		       IF (GFOUND) THEN
+	      	          START_BULL = 0
+		          IF (REVERSE) START_BULL = NBULL - 1
+		          OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	                  FOLDER_NUMBER = -1
+		          FOLDER1 = FOLDER1_DESCRIP(
+     &		          		:INDEX(FOLDER1_DESCRIP,' '))
+	                  CALL SELECT_FOLDER(.FALSE.,IER)
+		          IF (.NOT.IER) THEN
+		             FOLDER_NUMBER = OLD_FOLDER_NUMBER
+		             GFOUND = .FALSE.
+		          ELSE
+	   	             IF (FEEDBACK) WRITE (6,'('' Searching '',A)')
+     &		          		FOLDER_NAME(:TRIM(FOLDER_NAME))
+		             CHANGE = .TRUE.
+		             NFOLDER = -FOLDER_NUMBER
+		          END IF
+		       ELSE
+		          NFOLDER = 0
+		       END IF
+		    END DO
+		    CALL CLOSE_BULLFOLDER
+		    IF (NFOLDER.EQ.0) NGROUP = NGROUP - 1
+		    IF (NFOLDER.EQ.0.AND.NGROUP.GT.0) THEN
+		       CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+		       GLEN = TRIM(GROUP)
+		       NFOLDER = -1000
+		    END IF
+	         END DO
+		 IF (FLAG.EQ.1) THEN
+		    WRITE (6,'('' Search aborted.'')')
+		    NFOLDER = 0
+		 END IF
+	     	 CALL CANCEL_CTRLC_AST
+	      END IF
+	   END IF
+	END DO
+
+	IF (FOUND.EQ.-3) FOUND = 0
+
+	IF (FOUND.GT.0) THEN
+	   BULL_POINT = FOUND - 1
+	   CALL READ_MSG(READ_COUNT,BULL_POINT+1) ! Read next bulletin
+	ELSE IF (FOUND.EQ.0) THEN
+	   IF (CHANGE) THEN 
+  	      WRITE (6,'('' No matches found in current folder: '',A)')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   ELSE
+  	      WRITE (6,'('' No matches found.'')')
+	   END IF
+	ELSE IF (FOUND.EQ.-2) THEN
+	   IF (CHANGE) THEN 
+	      WRITE (6,'('' ERROR: No more messages in current folder: ''
+     &			,A)') FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   ELSE
+	      WRITE (6,'('' ERROR: No more messages.'')')
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_SEARCH(FOUND,SEARCH_STRING,SEARCH_NUM,SEARCH_LEN,
+     &	        MATCH_INPUT,START_BULL,REVERSE,SUBJECT,REPLY,FILES,START,
+     &		FROM_SEARCH,NEGATE,CHANGE)
+C
+C  SUBROUTINE GET_SEARCH
+C
+C  FUNCTION: Search for bulletin with specified string
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) SEARCH_STRING
+
+	DIMENSION SEARCH_LEN(1)
+	DIMENSION MATCH_FOUND(10)
+
+	CHARACTER*132 SAVE_STRING
+	DATA SAVE_STRING/' '/
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	COMMON /NEXT/ NEXT
+	LOGICAL NEXT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	CHARACTER*4 SAVECMD 
+
+	CHARACTER*128 DESCRIP1
+
+	FOUND = -1
+
+	CALL DISABLE_CTRL
+
+	CALL DECLARE_CTRLC_AST
+
+	IF (TRIM(SEARCH_STRING).EQ.0) THEN
+	   IER1 = .FALSE.
+	ELSE
+	   IER1 = .TRUE.
+	END IF
+	
+	IF (.NOT.IER1.AND..NOT.REPLY.AND.
+     &      (SUBJECT.OR.SEARCH_MODE.NE.1)) THEN
+						! If no search string entered
+	   SEARCH_STRING = SAVE_STRING		! use saved search string
+	   IF (TRIM(SAVE_STRING).EQ.0) THEN
+	      WRITE (6,'('' No search string present.'')')
+	      CALL CANCEL_CTRLC_AST
+	      CALL ENABLE_CTRL
+	      RETURN
+	   END IF
+	   IF (STEP_BULL.EQ.-1) START_BULL = START_BULL - 2
+	ELSE IF (.NOT.IER1.AND.SEARCH_MODE.EQ.1.AND..NOT.REPLY) THEN
+	   SEARCH_STRING = SAVE_STRING		! use saved search string
+	   IF (STEP_BULL.EQ.-1) START_BULL = START_BULL - 2
+	END IF
+
+	IF (FILES) CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(0,IER)
+
+	OLD_SEARCH_MODE = SEARCH_MODE
+	OLD_MATCH_MODE = MATCH_MODE
+
+	IF (IER1) THEN				! If string entered
+	   IF (SUBJECT) THEN
+	      SEARCH_MODE = 3
+	   ELSE IF (FROM_SEARCH) THEN    
+	      SEARCH_MODE = 4
+	   ELSE
+	      SEARCH_MODE = 2
+	   END IF
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	   OLD_REVERSE = REVERSE
+	ELSE IF (SUBJECT.AND.SEARCH_MODE.NE.3) THEN
+	   SEARCH_MODE = 3
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	ELSE IF (FROM_SEARCH.AND.SEARCH_MODE.NE.4) THEN
+	   SEARCH_MODE = 4
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	ELSE IF (REPLY) THEN
+	   OLD_REVERSE = REVERSE
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	   CALL READDIR(BULL_POINT,IER)
+	   IF (BULL_POINT+1.NE.IER) THEN
+	      WRITE (6,'('' ERROR: No message being read.'')')
+	      IF (FILES) CALL CLOSE_BULLDIR
+	      CALL CANCEL_CTRLC_AST
+	      CALL ENABLE_CTRL
+	      RETURN
+	   ELSE
+	      SEARCH_MODE = 1
+	      SEARCH_STRING = DESCRIP
+	      IF (STREQ(DESCRIP(:4),'RE: ').AND.TRIM(DESCRIP).GE.
+     &		 LEN(DESCRIP)-1) THEN
+	       	 IF (FILES) CALL OPEN_BULLFIL_SHARED
+	         IF (REMOTE_SET) THEN
+		    CALL REMOTE_READ_MESSAGE(BULL_POINT,IER)
+	            IF (IER.GT.0) THEN
+	               CALL DISCONNECT_REMOTE
+		       GO TO 900
+	            ELSE
+	               CALL GET_REMOTE_MESSAGE(IER)
+		       IF (IER.GT.0) GO TO 900
+	            END IF
+	         END IF
+	         ILEN = LINE_LENGTH + 1
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	         IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	         END IF
+	         IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	            SEARCH_STRING = INPUT(11:)
+	            SEARCH_STRING = SEARCH_STRING(:LEN(DESCRIP))
+		 ELSE
+	            SEARCH_STRING = DESCRIP(5:)
+	         END IF
+	       	 IF (FILES) CALL CLOSE_BULLFIL
+	      ELSE IF (STREQ(DESCRIP(:4),'RE: ')) THEN 
+	         SEARCH_STRING = DESCRIP(5:)
+	      END IF
+	      SEARCH_LEN(1) = TRIM(SAVE_STRING)
+	      IF (REVERSE) START_BULL = START_BULL - 2
+	   END IF
+	ELSE
+	   SEARCH_NUM = OLD_SEARCH_NUM
+	   IF (SEARCH_LEN(1).EQ.0) SEARCH_LEN(1) = TRIM(SAVE_STRING)
+	   IF (OLD_REVERSE) THEN
+	      START_BULL = MIN(START_BULL,NBULL-1)
+	      END_BULL = 1
+	      STEP_BULL = -1
+	   ELSE
+	      END_BULL = NBULL
+	      STEP_BULL = 1
+	      START_BULL = MAX(0,START_BULL)
+	   END IF
+	END IF
+
+	OLD_SEARCH_NUM = SEARCH_NUM
+
+	SAVE_STRING = SEARCH_STRING
+
+	CALL STR$UPCASE(SEARCH_STRING,SEARCH_STRING)	! Make upper case
+
+	IF (IER1.OR.SEARCH_MODE.NE.OLD_SEARCH_MODE.OR.CHANGE.OR.
+     &	    MATCH_MODE.NE.OLD_MATCH_MODE.OR.REVERSE.OR.REPLY) THEN
+	   IF (.NOT.START.AND.SEARCH_MODE.NE.1) THEN  
+	      START_BULL = 0	! If starting message not specified, use first
+	      IF (REVERSE) START_BULL = NBULL - 1  ! or last
+	   END IF
+	   IF (REVERSE) THEN
+	      START_BULL = MIN(START_BULL,NBULL-1)
+	      END_BULL = 1
+	      STEP_BULL = -1
+	   ELSE
+	      END_BULL = NBULL
+	      STEP_BULL = 1
+	      START_BULL = MAX(0,START_BULL)
+	   END IF
+	END IF
+
+	IF ((START_BULL+1.GT.NBULL.AND.STEP_BULL.EQ.1).OR.
+     &	    (START_BULL+1.EQ.0)) THEN
+	   FOUND = -2
+	   IF (FILES) CALL CLOSE_BULLDIR
+	   CALL CANCEL_CTRLC_AST
+	   CALL ENABLE_CTRL
+	   SEARCH_STRING = ' '
+	   RETURN
+	END IF
+
+	IF (FILES) CALL OPEN_BULLFIL_SHARED
+
+	NEWGROUP = .TRUE.
+	NEXT = STEP_BULL.EQ.1
+	SAVECMD = INCMD(:4)
+	IF (STEP_BULL.EQ.-1) INCMD(:4) = 'BACK'
+
+	SAVE_BULL_SEARCH = 0
+	BULL_SEARCH = START_BULL+1
+	DO WHILE ((STEP_BULL.EQ.1.AND.BULL_SEARCH.LE.END_BULL).OR.
+     &		(STEP_BULL.EQ.-1.AND.BULL_SEARCH.GE.MAX(1,F_START)))
+	   CALL READDIR(BULL_SEARCH,IER)	! Get bulletin directory entry
+	   IF (READ_TAG) THEN
+	      IF (STEP_BULL.EQ.-1) THEN
+		 CALL GET_THIS_TAG(FOLDER_NUMBER,IER,BULL_SEARCH,DUMMY)
+	 	 IF (IER.NE.0) THEN
+		    CALL GET_PREVIOUS_TAG(FOLDER_NUMBER,IER,
+     &			BULL_SEARCH,DUMMY)
+		 END IF
+	      ELSE
+		 CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,
+     &			BULL_SEARCH,DUMMY)
+	      END IF
+	      IF (IER.EQ.0) THEN
+		 IER = BULL_SEARCH + 1
+	      ELSE
+		 GO TO 800
+	      END IF
+	   END IF
+	   IF (REMOTE_SET.EQ.3.AND.SAVE_BULL_SEARCH.EQ.BULL_SEARCH) GO TO 800
+	   SAVE_BULL_SEARCH = BULL_SEARCH
+	   IF (IER.EQ.BULL_SEARCH+1.AND.SEARCH_MODE.NE.2) THEN
+	      IF (SEARCH_MODE.EQ.4) THEN
+	         CALL STR$UPCASE(DESCRIP1,FROM)
+	      ELSE
+		 IF (LEN(DESCRIP).EQ.TRIM(DESCRIP)) THEN
+	            IF (REMOTE_SET) THEN
+		       CALL REMOTE_READ_MESSAGE(BULL_SEARCH,IER)
+	               IF (IER.GT.0) THEN
+	                  CALL DISCONNECT_REMOTE
+		          GO TO 900
+	               ELSE
+	                  CALL GET_REMOTE_MESSAGE(IER)
+		          IF (IER.GT.0) GO TO 900
+	               END IF
+	            END IF
+		    ILEN = LINE_LENGTH + 1
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END IF
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+		       DESCRIP1 = INPUT(7:)
+		    END IF
+	            CALL STR$UPCASE(DESCRIP1,DESCRIP1)
+		 ELSE
+	            CALL STR$UPCASE(DESCRIP1,DESCRIP)
+		 END IF
+	      END IF
+	      IF ((SEARCH_MODE.GE.3.AND.MATCH(DESCRIP1,SEARCH_STRING,
+     &		  SEARCH_LEN,SEARCH_NUM,MATCH_MODE)).OR.
+     &		  (SEARCH_MODE.EQ.1.AND.(DESCRIP1.EQ.SEARCH_STRING.OR.
+     &		  (TRIM(SEARCH_STRING).EQ.LEN(DESCRIP).AND.
+     &		   DESCRIP1(:LEN(DESCRIP)).EQ.SEARCH_STRING).OR.
+     &		   (STREQ(DESCRIP1(:4),'RE: ').AND.DESCRIP1(5:).EQ.
+     &		   SEARCH_STRING(:MIN(TRIM(SEARCH_STRING),LEN(DESCRIP1)-4))
+     &		   )))) THEN
+                 IF (.NOT.NEGATED) THEN
+		    FOUND = BULL_SEARCH
+		    GO TO 900
+	         END IF   
+	      ELSE IF (FLAG.EQ.1) THEN
+		 WRITE (6,'('' Search aborted.'')')
+		 FOUND = -3
+		 GO TO 900
+              ELSE IF (NEGATED) THEN 
+                 FOUND = BULL_SEARCH
+                 GO TO 900
+	      END IF
+	   END IF
+	   IF (IER.EQ.BULL_SEARCH+1.AND.SEARCH_MODE.EQ.2) THEN
+	      IF (REMOTE_SET) THEN
+		 CALL REMOTE_READ_MESSAGE(BULL_SEARCH,IER)
+	         IF (IER.GT.0) THEN
+	            CALL DISCONNECT_REMOTE
+		    GO TO 900
+	         ELSE
+	            CALL GET_REMOTE_MESSAGE(IER)
+		    IF (IER.GT.0) GO TO 900
+	         END IF
+	      END IF
+	      ILEN = LINE_LENGTH + 1
+              MATCHES = 0
+	      DO I=1,SEARCH_NUM
+		 MATCH_FOUND(I) = .FALSE.
+	      END DO
+	      DO WHILE (ILEN.GT.0)
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	         CALL STR$UPCASE(INPUT,INPUT)	! Make upper case
+		 J = 1
+		 DO I=1,SEARCH_NUM
+		    IF (.NOT.MATCH_FOUND(I)) THEN
+		       MATCH_FOUND(I) = INDEX(INPUT,
+     &				SEARCH_STRING(J:J+SEARCH_LEN(I)-1)).GT.0
+		       IF (MATCH_FOUND(I)) MATCHES = MATCHES + 1
+		    END IF
+		    J = J + SEARCH_LEN(I)
+	         END DO
+		 IF ((MATCHES.GT.0.AND.MATCH_MODE.EQ.0).OR.
+     &	             (MATCHES.EQ.SEARCH_NUM.AND.MATCH_MODE.EQ.1)) THEN
+		    FOUND = BULL_SEARCH
+		    IF (.NOT.NEGATED) GO TO 900
+		 ELSE IF (FLAG.EQ.1) THEN
+		    WRITE (6,'('' Search aborted.'')')
+		    FOUND = -3
+		    GO TO 900
+		 END IF
+	      END DO
+	      IF (MATCHES.EQ.1.AND.MATCH_MODE.EQ.2) THEN
+		 FOUND = BULL_SEARCH
+		 IF (.NOT.NEGATED) GO TO 900
+              END IF
+              IF (NEGATED) THEN 
+                 IF (FOUND.EQ.-1) THEN
+                    FOUND = BULL_SEARCH
+ 		    GO TO 900
+		 ELSE
+		    FOUND = -1
+	         END IF
+	      END IF
+	   END IF
+	   BULL_SEARCH = BULL_SEARCH + STEP_BULL
+	END DO
+
+800	FOUND = 0
+
+900	IF (FOUND.LE.0.AND.REMOTE_SET.EQ.3) THEN
+	   NEXT = .FALSE.
+	   CALL READDIR(BULL_POINT,IER)
+	   CALL REMOTE_READ_MESSAGE(BULL_POINT,IER)
+	   IF (IER.GT.0) THEN
+	      CALL DISCONNECT_REMOTE
+	   ELSE
+	      CALL GET_REMOTE_MESSAGE(IER)
+	   END IF
+	END IF
+	IF (FILES) CALL CLOSE_BULLFIL		! End of bulletin file read
+	IF (FILES) CALL CLOSE_BULLDIR
+	CALL CANCEL_CTRLC_AST
+	CALL ENABLE_CTRL
+
+	IF (.NOT.IER1) SEARCH_STRING = ' '
+	NEXT = .FALSE.
+	IF (STEP_BULL.EQ.-1) INCMD(:4) = SAVECMD
+
+	RETURN
+	END
+ 
+
+
+
+        LOGICAL FUNCTION MATCH(INPUT,SEARCH_STRING,SEARCH_LEN,
+     &                         SEARCH_NUM,MATCH_MODE)
+
+        IMPLICIT INTEGER (A - Z)
+
+	DIMENSION SEARCH_LEN(1)
+
+        CHARACTER*(*) INPUT,SEARCH_STRING
+ 
+        OLD_MATCH = .FALSE.
+
+	J = 1
+
+	DO I=1,SEARCH_NUM
+	   MATCH = INDEX(INPUT,SEARCH_STRING(J:J+SEARCH_LEN(I)-1)).GT.0
+           IF (MATCH.AND.MATCH_MODE.EQ.0) RETURN
+           IF (.NOT.MATCH.AND.MATCH_MODE.EQ.1) RETURN
+           IF (OLD_MATCH.AND.MATCH.AND.MATCH_MODE.EQ.2) THEN
+              MATCH = .FALSE.
+	      RETURN
+           END IF
+	   J = J + SEARCH_LEN(I)
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UNDELETE
+C
+C  SUBROUTINE UNDELETE
+C
+C  FUNCTION: Undeletes deleted message.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   WRITE (6,'('' Cannot UNDELETE messages in this folder.'')')
+	   RETURN
+	END IF
+C
+C  Get the bulletin number to be undeleted.
+C
+
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   BULL_DELETE = BULL_POINT	! Delete the file we are reading
+	ELSE
+	   IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	      DECODE(LEN_P,5,BULL_PARAMETER,ERR=920) BULL_DELETE	! Yes
+5	      FORMAT(I<LEN_P>)
+	   ELSE IF (BULL_POINT.EQ.0) THEN  ! No.  Have we read a bulletin?
+	      GO TO 910			! No, then error.
+	   ELSE
+	      BULL_DELETE = BULL_POINT	! Delete the file we are reading
+	   END IF
+	END IF
+
+	IF (BULL_DELETE.LE.0) GO TO 920
+
+C
+C  Check to see if specified bulletin is present, and if the user
+C  is permitted to delete the bulletin.
+C
+
+	CALL OPEN_BULLDIR
+
+	CALL READDIR(BULL_DELETE,IER)	! Get info for specified bulletin
+
+	IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	   WRITE(6,1030)	! If not, then error out
+	   GOTO 100
+	END IF
+
+	IF (USERNAME.NE.FROM) THEN	! If doesn't match owner of bulletin,
+	   IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.	! Privileges or
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN				! folder owner?
+	      WRITE(6,1040)		! Then error out.
+	      GO TO 100
+	   ELSE
+	      CALL READDIR(BULL_DELETE,IER) ! Get info for specified bulletin
+	      IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	         WRITE(6,1030)		! If not, then error out
+	         GOTO 100
+	      END IF
+	   END IF
+	END IF
+
+	IF ((SYSTEM.AND.7).LE.1) THEN	! General or System message
+	   IF (EXDATE(8:11).LT.'1900') EXDATE(8:9) = '19'
+	   IF (EXDATE(8:11).LT.'1995') EXDATE(8:9) = '20'
+	ELSE				! Permanent or Shutdown
+	   IF (EXDATE(2:2).EQ.'-') THEN
+	      EXDATE = EXDATE(:6)//'21'//EXDATE(9:)
+	   ELSE
+	      EXDATE = EXDATE(:7)//'21'//EXDATE(10:)
+	   END IF
+	END IF
+
+	IF (.NOT.REMOTE_SET) THEN
+	   CALL WRITEDIR(BULL_DELETE,IER)	! Update message expiration date
+	   IF (INCMD(:3).NE.'DIR') THEN
+	      WRITE (6,'('' Message was undeleted.'')')
+	   END IF
+	ELSE
+	   WRITE (REMOTE_UNIT,'(5A)',IOSTAT=IER)
+     &      11,BULL_DELETE,DESCRIP,EXDATE,EXTIME
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (I.NE.LEN(FOLDER1_COM)) THEN
+		 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      ELSE IF (INCMD(:3).NE.'DIR') THEN
+	         WRITE (6,'('' Message was undeleted.'')')
+	      END IF
+	   ELSE
+	      CALL DISCONNECT_REMOTE
+	   END IF
+	END IF
+
+100	CALL CLOSE_BULLDIR
+
+900	RETURN
+
+910	WRITE(6,1010)
+	GO TO 900
+
+920	WRITE(6,1020)
+	GO TO 900
+
+1010	FORMAT(' ERROR: You are not reading any message.')
+1020	FORMAT(' ERROR: Specified message number has incorrect format.')
+1030	FORMAT(' ERROR: Specified message was not found.')
+1040	FORMAT(' ERROR: Message was not undeleted. Not owned by you.')
+
+	END
+
+
+
+
+	SUBROUTINE ADD_PROTOCOL(INPUT,ILEN)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLNEWS.INC'
+
+	CHARACTER*20 MAIL_PROTOCOL
+
+	CHARACTER*(*) INPUT
+
+	CHARACTER*256 INPUT_OUT
+	CHARACTER*128 TEMP
+
+	INPUT_OUT = ' '
+
+	I = 0
+
+	DO WHILE (I.LT.TRIM(INPUT))
+	   INPUT = INPUT(I+1:)
+	   IF (I.GT.0) INPUT_OUT = INPUT_OUT(:TRIM(INPUT_OUT))//','
+	   J = INDEX(INPUT,',')
+	   IF (INDEX(INPUT,'(').LT.J.AND.INDEX(INPUT,')').GT.J) THEN 
+	      INPUT = INPUT(:INDEX(INPUT,'(')-1)//INPUT(INDEX(INPUT,')')+1:)
+	   END IF
+	   I = MINGT0(INDEX(INPUT,','),TRIM(INPUT)+1)
+	   IF (INDEX(INPUT,',').EQ.I.AND.INDEX(INPUT(:I),'@').EQ.0)
+     &		I = TRIM(INPUT)+1
+	   TEMP = INPUT(:I-1)
+	   CALL ADD_PROTOCOL_SUB(TEMP)
+	   INPUT_OUT = INPUT_OUT(:TRIM(INPUT_OUT))//TEMP(:TRIM(TEMP))
+	END DO
+
+	INPUT = INPUT_OUT
+
+	IF (ILEN.NE.0) ILEN = TRIM(INPUT)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_PROTOCOL_SUB(INPUT)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLNEWS.INC'
+
+	CHARACTER*20 MAIL_PROTOCOL
+
+	CHARACTER*(*) INPUT
+
+	DATA LMAIL/0/
+
+	IF (LMAIL.EQ.-1) RETURN
+
+	IF (INDEX(INPUT,'@').EQ.0.OR.INDEX(INPUT,'%"').GT.0) RETURN
+
+	I = INDEX(INPUT,'<')
+	IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN ! Name may be of form
+	   INPUT = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+						! personal-name <net-name>
+	END IF
+
+	IF (LMAIL.EQ.0) THEN
+	   IF (.NOT.SYS_TRNLNM('BULL_NEWS_MAILER',MAIL_PROTOCOL)) THEN
+	      MAIL_PROTOCOL = MAILER
+	   END IF
+	   LMAIL = TRIM(MAIL_PROTOCOL)
+	   IF (LMAIL.GT.0.AND.MAIL_PROTOCOL(LMAIL:LMAIL).NE.'%') THEN
+	      MAIL_PROTOCOL = MAIL_PROTOCOL(:LMAIL)//'%'
+	      LMAIL = LMAIL + 1
+	   END IF
+	   IF (LMAIL.EQ.0) THEN
+	      LMAIL = -1
+	      RETURN
+	   END IF
+	END IF
+
+	I = INDEX(INPUT,'@')
+	IF (I.GT.0) THEN
+	   INPUT = INPUT(:INDEX(INPUT(I:),' ')+I-2)
+	   IF (INDEX(INPUT(I:),'(').GT.0)
+     &		INPUT = INPUT(:INDEX(INPUT(I:),'(')+I-2)
+	END IF
+
+	INPUT = MAIL_PROTOCOL(:LMAIL)//'"'//INPUT(:TRIM(INPUT))//'"'
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin3.for b/decus/vmslt00a/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..cf5b221f3799e5fff75d87d37bc48ff1e8f55524
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin3.for
@@ -0,0 +1,2518 @@
+C
+C  BULLETIN3.FOR, Version 11/2/98
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE UPDATE
+C
+C  SUBROUTINE UPDATE
+C
+C  FUNCTION:  Searches for bulletins that have expired and deletes them.
+C
+C  NOTE:  Assumes directory file is already opened.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	CHARACTER*12 TEMP_DATE,TEMP_EXDATE,TEMP_NOSYSDATE
+	CHARACTER*12 TEMP_TIME,TEMP_EXTIME,TEMP_NOSYSTIME
+
+	IF (REMOTE_SET.AND.
+     &		NODE_AREA.GT.0.AND.BTEST(FOLDER_FLAG,2)) THEN
+	   CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	END IF
+
+	IF (TEST_BULLCP().OR.REMOTE_SET) RETURN
+					! BULLCP cleans up expired bulletins
+
+	ENTRY UPDATE_ALWAYS		! Entry to skip BULLCP test
+
+	TEMP_EXDATE = '5-NOV-2100'  ! If a bulletin gets deleted, and there are
+	TEMP_EXTIME = '00:00:00.00' ! are no more bulletins, this is the value
+				    ! assigned to the latest expiration date
+
+	TEMP_DATE = '5-NOV-1956' 	! Storage for computing newest
+	TEMP_TIME = '00:00:00.00'	! bulletin date if deletion occurs
+
+	TEMP_NOSYSDATE = '5-NOV-1956' 	! Storage for computing newest
+	TEMP_NOSYSTIME = '00:00:00.00'	! non-system bulletin date
+
+	BULL_ENTRY = 1				! Init bulletin pointer
+	UPDATE_DONE = 0			! Flag showing bull has been deleted
+
+	NEW_SHUTDOWN = 0
+	OLD_SHUTDOWN = SHUTDOWN
+
+	DO WHILE (UPDATE_DONE.GE.0)
+	   CALL READDIR(BULL_ENTRY,IER)		! Get next directory entry
+	   IF (IER.EQ.BULL_ENTRY) GO TO 100	! ERROR: Not found
+	   IF ((SYSTEM.AND.7).LE.3.OR.(OLD_SHUTDOWN.EQ.0
+						! If not shutdown, or time
+     &	     .AND.(SYSTEM.AND.4).EQ.4)) THEN	! to delete shutdowns?
+	    IF ((SYSTEM.AND.4).EQ.4) THEN	! Shutdown bulletin?
+	       IF (NODE_AREA.GT.0) THEN
+	          READ (EXTIME(1:2),'(I2)') I
+	          READ (EXTIME(4:5),'(I2)') NODE_NUMBER_MSG
+		  NODE_NUMBER_MSG = NODE_NUMBER_MSG + I*60
+	          READ (EXTIME(7:8),'(I2)') I
+	          READ (EXTIME(10:11),'(I2)') NODE_AREA_MSG
+		  NODE_AREA_MSG = NODE_AREA_MSG + I*60
+	          IF (NODE_NUMBER_MSG.EQ.NODE_NUMBER.AND.
+     &		      NODE_AREA_MSG.EQ.NODE_AREA) THEN
+		     DIFF = 0
+		  ELSE
+		     DIFF = 1
+	             NEW_SHUTDOWN = NEW_SHUTDOWN + 1
+		  END IF
+	       END IF
+	    ELSE
+	       DIFF = COMPARE_DATE(EXDATE,' ')	! Has expiration date passed?
+	       IF (DIFF.EQ.0) DIFF = COMPARE_TIME(EXTIME,' ')
+	    END IF
+	    IF (DIFF.LE.0) THEN			! If so then delete bulletin
+	      CALL DELETE_ENTRY(BULL_ENTRY)	! Delete bulletin entry
+	      IF (UPDATE_DONE.EQ.0) THEN	! If this is first deleted file
+	         UPDATE_DONE = BULL_ENTRY	! store it to use for reordering
+	      END IF				! directory file.
+	    ELSE IF ((SYSTEM.AND.7).LE.3) THEN	! Expiration date hasn't passed
+		! If a bulletin is deleted, we'll have to update the latest
+		! expiration date. The following does that.
+	      DIFF = COMPARE_DATE(EXDATE,TEMP_EXDATE)
+	      IF (DIFF.LT.0.OR.(DIFF.EQ.0.AND.
+     &		COMPARE_TIME(EXTIME,TEMP_EXTIME).LT.0)) THEN
+	         TEMP_EXDATE = EXDATE		! If this is the latest exp
+	         TEMP_EXTIME = EXTIME		! date seen so far, save it.
+	      END IF
+	      TEMP_DATE = DATE			! Keep date after search
+	      TEMP_TIME = TIME			! we have the last message date
+	      IF (.NOT.BTEST(SYSTEM,0)) THEN
+		 TEMP_NOSYSDATE = DATE
+		 TEMP_NOSYSTIME = TIME
+	      END IF
+	    END IF
+	   ELSE
+	      TEMP_DATE = DATE
+	      TEMP_TIME = TIME
+	      IF (.NOT.BTEST(SYSTEM,0)) THEN
+		 TEMP_NOSYSDATE = DATE
+		 TEMP_NOSYSTIME = TIME
+	      END IF
+	   END IF
+	   BULL_ENTRY = BULL_ENTRY + 1
+	END DO
+
+100	IF (UPDATE_DONE.GT.0) THEN		! Reorder directory file
+	   CALL CLEANUP_DIRFILE(UPDATE_DONE)	! due to deleted entries
+	END IF
+
+	DATE = NEWEST_DATE
+	TIME = NEWEST_TIME
+	CALL READDIR(0,IER)
+	SHUTDOWN = NEW_SHUTDOWN
+	NEWEST_EXDATE = TEMP_EXDATE
+	DIFF = COMPARE_DATE(NEWEST_EXDATE,' ')
+	IF (DIFF.GT.20*356) NEWEST_EXDATE = '5-NOV-2100'
+	NEWEST_EXTIME = TEMP_EXTIME
+	NEWEST_DATE = TEMP_DATE
+	NEWEST_TIME = TEMP_TIME
+	CALL WRITEDIR(0,IER)
+	SYSTEM = 0			! Updating last non-system date/time
+	NEWEST_DATE = TEMP_NOSYSDATE
+	NEWEST_TIME = TEMP_NOSYSTIME
+	CALL UPDATE_FOLDER
+	SYSTEM = 1			! Now update latest date/time
+	NEWEST_DATE = TEMP_DATE
+	NEWEST_TIME = TEMP_TIME
+	CALL UPDATE_FOLDER
+
+	IF (NODE_AREA.GT.0.AND.BTEST(FOLDER_FLAG,2)) THEN ! Shutdowns deleted?
+	   CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)		  ! Save that info
+	END IF
+
+C
+C  If newest message date has been changed, must change it in BULLUSER.DAT
+C  and also see if it affects notification of new messages to users
+C
+	IF (TEMP_DATE.NE.DATE.OR.TEMP_TIME.NE.TIME) THEN
+	   CALL UPDATE_LOGIN(.FALSE.)
+	END IF
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE UPDATE_READ(USERFILE_OPEN)
+C
+C  SUBROUTINE UPDATE_READ
+C
+C  FUNCTION:
+C	Store the latest date that user has used the BULLETIN facility.
+C	If new bulletins have been added, alert user of the fact.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($PRVDEF)'
+
+	CHARACTER TODAY*24
+
+	DIMENSION TODAY_BTIM(2),READ_BTIM_SAVE(2)
+
+	LOGICAL MODIFY_SYSTEM /.TRUE./
+
+C
+C  Update user's latest read time in his entry in BULLUSER.DAT.
+C
+	IF (.NOT.USERFILE_OPEN) THEN
+	   CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+	END IF
+
+	CALL READ_USER_FILE_HEADER(IER)
+
+	IF (IER.NE.0) THEN			! If header not present, exit
+	   IF (.NOT.USERFILE_OPEN) CALL CLOSE_BULLUSER
+	   RETURN
+	ELSE IF (USERPRIV(1).EQ.-1.AND.USERPRIV(2).EQ.-1) THEN
+						! If header present, but no
+	   DO I=1,FLONG				! SET_FLAG and NOTIFY_FLAG
+	      SET_FLAG_DEF(I) = 0		! information, write default
+	      NOTIFY_FLAG_DEF(I) = 0		! flags.
+	      BRIEF_FLAG_DEF(I) = 0
+	   END DO
+	   SET_FLAG_DEF(1) = 1
+	   USERPRIV(1) = PRV$M_OPER.OR.PRV$M_CMKRNL.OR.PRV$M_SETPRV
+	   USERPRIV(2) = 0
+	   REWRITE (4) USER_HEADER
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get today's time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	UNLOCK 4
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER1)
+
+	IF (IER1.EQ.0) THEN			! If entry found, update it
+	   IF (USERFILE_OPEN.EQ.0) THEN
+	      READ_BTIM_SAVE(1) = READ_BTIM(1)
+	      READ_BTIM_SAVE(2) = READ_BTIM(2)
+	      READ_BTIM(1) = TODAY_BTIM(1)
+	      READ_BTIM(2) = TODAY_BTIM(2)
+	      REWRITE (4) USER_ENTRY
+     	      READ_BTIM(1) = READ_BTIM_SAVE(1)
+	      READ_BTIM(2) = READ_BTIM_SAVE(2)
+	   END IF
+	ELSE					! If no entry create a new entry
+	   NEW_FLAG(1) = 143
+	   NEW_FLAG(2) = 0
+	   LOGIN_BTIM(1) = TODAY_BTIM(1)
+	   LOGIN_BTIM(2) = TODAY_BTIM(2)
+	   READ_BTIM(1) = TODAY_BTIM(1)
+	   READ_BTIM(2) = TODAY_BTIM(2)
+	   CALL WRITE_USER_FILE_NEW(IER)
+	END IF
+
+	IF (MODIFY_SYSTEM) THEN
+	   CALL MODIFY_SYSTEM_LIST(1)
+	   MODIFY_SYSTEM = .FALSE.
+	END IF
+
+	IF (.NOT.USERFILE_OPEN) THEN
+	   CALL CLOSE_BULLUSER			! All finished with BULLUSER
+	END IF
+
+	RETURN					! to go home...
+
+	END
+
+
+
+
+	SUBROUTINE FIND_NEWEST_BULL
+C
+C  SUBROUTINE FIND_NEWEST_BULL
+C
+C	If new bulletins have been added, alert user of the fact and
+C	set the next bulletin to be read to the first new bulletin.
+C
+C  OUTPUTS:
+C	BULL_POINT  -  If -1, no new bulletins to read, else there are.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INTEGER DIR_BTIM(2)
+
+C
+C  Now see if bulletins have been added since the user's previous
+C  read time.  If they have, then search for the first new bulletin.
+C  Ignore new bulletins that are owned by the user or system notices
+C  that have not been added since the user has logged in.
+C
+	BULL_POINT = -1				! Init bulletin pointer
+
+	CALL OPEN_BULLDIR_SHARED		! Yep, so get directory file
+	CALL READDIR(0,IER)			! Get # bulletins from header
+	IF (IER.EQ.1) THEN
+	   CALL GET_NEWEST_MSG(LAST_READ_BTIM(1,FOLDER_NUMBER+1),START)
+	   IF (START.LE.0) THEN
+	      BULL_POINT = START
+	      CALL CLOSE_BULLDIR
+	      RETURN
+	   END IF
+	   DO WHILE (START.LE.NBULL.AND.(FROM.EQ.USERNAME.OR.SYSTEM))
+	      IF (FROM.NE.USERNAME) THEN	! Ignore bull if owner is user
+	         IF (SYSTEM) THEN		! If system bulletin
+	            CALL SYS_BINTIM(DATE//' '//TIME,DIR_BTIM)
+	            DIFF = COMPARE_BTIM(LOGIN_BTIM,DIR_BTIM)
+		    IF (DIFF.GT.0) THEN
+		       START = START + 1
+	               CALL READDIR(START,IER)
+		    ELSE			! SYSTEM bulletin was not seen
+		       SYSTEM = 0		! so force exit to read it.
+		    END IF
+	         END IF
+	      ELSE
+		 START = START + 1
+		 CALL READDIR(START,IER)
+		 IF (IER.NE.START+1) START = NBULL + 1
+	      END IF
+	   END DO
+	   IF (START.LE.NBULL) BULL_POINT = START - 1
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_EXPIRED(EXPDAT,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*24 EXPDAT
+	CHARACTER*24 TODAY
+
+	DIMENSION EXTIME_BIN(2),NOW(2)
+
+	EXTERNAL CLI$_ABSENT
+
+	IER = SYS$ASCTIM(,TODAY,,)		! Get today's date
+
+	ILEN = 0
+	IERC = CLI$GET_VALUE('EXPIRATION',EXPDAT,ILEN)
+
+	PROMPT = .TRUE.
+
+	EXPIRE_LIMIT = F_EXPIRE_LIMIT
+	IF (REMOTE_SET.EQ.4.AND.EXPIRE_LIMIT.EQ.0)
+     &	   EXPIRE_LIMIT = NEWS_EXPIRE_LIMIT_DEFAULT
+
+5	IF (PROMPT) THEN
+	   IF (IERC.NE.%LOC(CLI$_ABSENT)) THEN	! Was value specified?
+	      PROMPT = .FALSE.
+	   ELSE
+	      DEFAULT_EXPIRE = FOLDER_BBEXPIRE
+	      IF (REMOTE_SET.EQ.4.AND.DEFAULT_EXPIRE.EQ.0)
+     &		 DEFAULT_EXPIRE = NEWS_EXPIRE_DEFAULT
+	      IF ((DEFAULT_EXPIRE.GT.EXPIRE_LIMIT.OR.DEFAULT_EXPIRE
+     &		  .EQ.0).AND.EXPIRE_LIMIT.GT.0.AND..NOT.
+     &	          FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+		 DEFAULT_EXPIRE = F_EXPIRE_LIMIT
+	      END IF
+	      IF (BTEST(FOLDER_FLAG,3).OR.
+     &		  REMOTE_SET.EQ.4) THEN		! NOPROMPT was set
+		 IF (DEFAULT_EXPIRE.LE.0) THEN		! If no expiration date
+	            SYSTEM = SYSTEM.OR.2		! make permanent
+	            EXPDAT = '5-NOV-2100 00:00:00.00'
+		 ELSE					! Else set expiration
+		    CALL GET_EXDATE(EXPDAT,DEFAULT_EXPIRE)
+		    EXPDAT = EXPDAT(:TRIM(EXPDAT))//' 00:00:00.00'
+		 END IF
+		 ILEN = TRIM(EXPDAT)
+	      ELSE
+		 IF (DEFAULT_EXPIRE.EQ.0) THEN	! Get expiration date
+	            WRITE(6,1030) TODAY(:INDEX(TODAY,'.')-4)
+		 ELSE IF (DEFAULT_EXPIRE.EQ.-1) THEN
+	            WRITE(6,1031) TODAY(:INDEX(TODAY,'.')-4)
+		 ELSE
+	            WRITE(6,1032) TODAY(:INDEX(TODAY,'.')-4),
+     &					DEFAULT_EXPIRE
+		 END IF
+		 WRITE (6,1035)
+	         CALL GET_LINE(EXPDAT,ILEN)	! Get EXPDAT line
+		 IF (ILEN.EQ.0.AND.DEFAULT_EXPIRE.NE.0) THEN
+		    IF (DEFAULT_EXPIRE.EQ.-1) THEN
+		       EXPDAT = '5-NOV-2100 00:00:00.00'
+		       SYSTEM = IBSET(SYSTEM,1)	! Indicate permanent message
+		    ELSE
+		       CALL GET_EXDATE(EXPDAT,DEFAULT_EXPIRE)
+		       EXPDAT = EXPDAT(:TRIM(EXPDAT))//' 00:00:00.00'
+		    END IF
+		    ILEN = TRIM(EXPDAT)
+		 END IF
+	      END IF
+	   END IF
+	ELSE
+	   RETURN
+	END IF
+
+	IF (ILEN.LE.0) THEN
+	   IER = 0
+	   RETURN
+	END IF
+
+	EXPDAT = EXPDAT(:ILEN)			! Change trailing zeros 2 spaces
+
+	IF (INDEX(EXPDAT,'-').EQ.0.AND.INDEX(EXPDAT,':').GT.0.AND.
+     &		INDEX(EXPDAT(:ILEN),' ').EQ.0) THEN	! Only time specified?
+	   EXPDAT = TODAY(:INDEX(TODAY(2:),' ')+1)//EXPDAT	! Add date
+	ELSE IF (INDEX(EXPDAT(6:),'-').EQ.0.AND.		! Date specified
+     &			INDEX(EXPDAT,'-').GT.0) THEN	! but no year?
+	   SPACE = INDEX(EXPDAT,' ') - 1			! Add year
+	   IF (SPACE.EQ.-1) SPACE = TRIM(EXPDAT) 
+	   YEAR = INDEX(TODAY(6:),'-')
+	   EXPDAT = EXPDAT(:SPACE)//TODAY(5+YEAR:9+YEAR)//EXPDAT(SPACE+1:)
+	END IF
+
+	CALL STR$UPCASE(EXPDAT,EXPDAT)		! Convert to upper case
+	IER = SYS_BINTIM(EXPDAT,EXTIME_BIN)
+	IF (IER.NE.1) THEN			! If not able to do so
+    	   WRITE(6,1040)			! tell user is wrong
+	   IER = 0				! Set error for return value
+	   GO TO 5				! Re-request date (if prompting)
+	END IF
+	IER = SYS$ASCTIM(TIMLEN,EXPDAT,EXTIME_BIN,)
+	IF (TIMLEN.EQ.16) THEN
+	   CALL SYS$GETTIM(NOW)
+	   CALL LIB$SUBX(NOW,EXTIME_BIN,EXTIME_BIN)
+	   IER = SYS$ASCTIM(TIMLEN,EXPDAT,EXTIME_BIN,)
+	END IF
+
+	IF (EXPDAT(2:2).EQ.'-') EXPDAT = '0'//EXPDAT
+	IER = COMPARE_DATE(EXPDAT(:11),TODAY(:11)) ! Compare date with today's
+	IF (IER.GT.EXPIRE_LIMIT.AND.EXPIRE_LIMIT.GT.0.AND.
+     &	    .NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   WRITE(6,1050) EXPIRE_LIMIT		! Expiration date > limit
+	   IER = 0				! Set error for return value
+	   GO TO 5				! Re-request date (if prompting)
+	END IF
+	IF (IER.EQ.0) IER = COMPARE_TIME(EXPDAT(13:23),TODAY(13:23))
+	IF (IER.LE.0) THEN			! If expiration date not future
+	   WRITE(6,1045)			! tell user
+	   IER = 0				! Set error for return value
+	   GO TO 5				! Re-request date (if prompting)
+	END IF
+
+	IF (PROMPT) THEN
+	   IF (BTEST(SYSTEM,1)) THEN		! Permanent message
+	      WRITE (6,'('' Message will be permanent.'')')
+	   ELSE
+	      WRITE (6,'('' Expiration date will be '',A,''.'')')
+     &		EXPDAT(:TRIM(EXPDAT))
+	   END IF
+	END IF
+
+	IER = 1
+
+	RETURN
+
+1030	FORMAT(' It is ',A,'. Specify when message expires.')
+1031	FORMAT(' It is ',A,'. Specify when message expires.',
+     &		' Default is permanent.')
+1032	FORMAT(' It is ',A,'. Specify when message expires.',
+     &		' Default is ',I3,' days.')
+1035    Format(' Enter absolute time: [dd-mmm-yyyy] hh:mm:ss ',
+     &		'or delta time: dddd hh:mm:ss')
+1040	FORMAT(' ERROR: Invalid date format specified.')
+1045	FORMAT(' ERROR: Specified time has already passed.')
+1050	FORMAT(' ERROR: Specified expiration period too large.'
+     &		' Limit is ',I3,' days.')
+
+	END
+
+
+	SUBROUTINE MAILEDIT(INFILE,OUTFILE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER*(*) INFILE,OUTFILE
+
+	CHARACTER*80 MAIL_EDIT,OUT
+	DATA MAIL_EDIT /' '/
+
+	CHARACTER*132 INPUT
+
+	CHARACTER*256 SPAWN_COMMAND
+
+	EXTERNAL ERROR_TRAP
+
+	IF (CAPTIVE(2)) THEN
+	   WRITE (6,'('' ERROR: /EDIT not allowed from CAPTIVE account.'')')
+	   RETURN
+	END IF
+
+	IF (MAIL_EDIT.EQ.' ') THEN
+	  IF (.NOT.SYS_TRNLNM('MAIL$EDIT',MAIL_EDIT)) THEN
+	    OPEN (UNIT=10,FILE='VMSMAIL_PROFILE',
+     &	     DEFAULTFILE='SYS$SYSTEM:VMSMAIL_PROFILE.DATA',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+	    IF (IER.EQ.0) THEN
+	      DO WHILE (REC_LOCK(IER))
+	         READ(10,'(A)',KEY=USERNAME,IOSTAT=IER) INPUT
+	      END DO
+	      CLOSE (UNIT=10)
+	      IF (IER.EQ.0) THEN
+		 INPUT = INPUT(32:)
+		 DO WHILE (TRIM(INPUT).GT.0)
+		    IF (ICHAR(INPUT(1:1)).EQ.8) THEN
+		       MAIL_EDIT = 'CALLABLE_'//INPUT(5:4+ICHAR(INPUT(3:3)))
+		       INPUT = ' '
+		    ELSE
+		       INPUT = INPUT(ICHAR(INPUT(3:3))+5:)
+	            END IF
+	         END DO
+	      END IF
+	    END IF
+	  END IF
+	  CALL STR$UPCASE(MAIL_EDIT,MAIL_EDIT)
+	END IF
+
+	OUT = OUTFILE
+	IF (TRIM(OUT).EQ.0) THEN
+	   OUT = INFILE
+	END IF
+
+	CALL DISABLE_PRIVS
+	CALL DECLARE_CTRLC_AST
+	IF (TRIM(MAIL_EDIT).GT.0
+     &		.AND.INDEX(MAIL_EDIT,'CALLABLE_').EQ.0) THEN
+	   IF (MAIL_EDIT(:1).EQ.'@') MAIL_EDIT = MAIL_EDIT(2:)
+	   IF (OUT.EQ.INFILE) THEN
+	      SPAWN_COMMAND = '$@'//MAIL_EDIT(:TRIM(MAIL_EDIT))
+     &		//' "" '//OUT(:TRIM(OUT))
+	   ELSE
+	      SPAWN_COMMAND = '$@'//MAIL_EDIT(:TRIM(MAIL_EDIT))
+     &		//' '//INFILE//' '//OUT(:TRIM(OUT))
+	   END IF
+	   CALL LIB$SPAWN(SPAWN_COMMAND)
+	ELSE
+	   IF (TRIM(MAIL_EDIT).EQ.0) MAIL_EDIT = 'CALLABLE_TPU'
+
+C           The string CALLABLE_ was found.  Extract the editor name from the
+C           string and look up the entry point in the shareable image.
+
+	   N = INDEX(MAIL_EDIT,'_')+1
+	   IER = LIB$FIND_IMAGE_SYMBOL(
+     &		MAIL_EDIT(N:TRIM(MAIL_EDIT))//'SHR',
+     &		MAIL_EDIT(N:TRIM(MAIL_EDIT))//'$EDIT',ENTRYADDR)
+	   IF (IER) THEN
+	      CONTEXT = 0
+	      IER1 = LIB$FIND_FILE(INFILE,INPUT,CONTEXT)
+	      IF (MAIL_EDIT.EQ.'CALLABLE_EDT') THEN
+	         IF (.NOT.IER1) THEN
+	            CALL EDT$EDIT('NL:',OUT)
+	         ELSE
+	            CALL EDT$EDIT(INFILE,OUT)
+	         END IF
+	      ELSE
+                 IF (.NOT.IER1) THEN
+                    CALL EDITMESSAGE(%VAL(ENTRYADDR),' ',OUT)
+                 ELSE
+                    CALL EDITMESSAGE(%VAL(ENTRYADDR),INFILE,OUT)
+                 END IF
+	      END IF
+	      CALL LIB$ESTABLISH(ERROR_TRAP)
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+              CALL LIB$REVERT
+	   ELSE
+	      WRITE(6,'('' Could not activate editor.'')')
+	   END IF
+        END IF
+	CALL CANCEL_CTRLC_AST
+	CALL ENABLE_PRIVS
+
+	RETURN
+	END
+
+
+
+        SUBROUTINE EDITMESSAGE(EDITOR,INFILE,OUTFILE)
+
+        CHARACTER*(*) INFILE,OUTFILE
+
+        EXTERNAL EDITOR
+
+        CALL EDITOR(INFILE,OUTFILE)
+
+        RETURN
+        END
+
+
+
+	SUBROUTINE CREATE_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRCDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /REALPROC/ REALPROCPRIV(2)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	LOGICAL*1 QUOTA(32)
+
+	DIMENSION IMAGEPRIV(2)
+
+	CHARACTER IMAGENAME*132,ANSWER*4
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: You do not have the privileges '',
+     &			''to execute the command.'')')
+	   CALL EXIT
+	END IF
+
+	JUST_STOP = CLI$PRESENT('STOP')
+
+	IF (JUST_STOP.AND..NOT.BTEST(REALPROCPRIV(1),PRV$V_SETPRV)) THEN
+	   WRITE (6,'('' ERROR: You need SETPRV to execute /STOP.'')')
+	   CALL EXIT
+	ELSE IF (.NOT.JUST_STOP.AND.
+     &			.NOT.BTEST(REALPROCPRIV(1),PRV$V_SYSNAM)) THEN
+	   CALL SYS$SETPRV(,,,IMAGEPRIV)
+	   IF (.NOT.BTEST(IMAGEPRIV(1),PRV$V_SYSNAM)) THEN
+	      WRITE (6,'('' ERROR: This new version of BULLETIN'',
+     &			'' needs to be installed with SYSNAM.'')')
+	      CALL EXIT
+	   END IF
+	END IF
+
+	IF (TEST_BULLCP()) THEN
+	   IF (.NOT.JUST_STOP) THEN
+	      WRITE (6,'('' BULLCP process running.
+     & Do you wish to kill it and restart a new one? '',$)')
+	      READ (5,'(A)') ANSWER(:1)
+	      IF (ANSWER(:1).NE.'Y'.AND.ANSWER(:1).NE.'y') CALL EXIT
+	   END IF
+
+	   CALL DELPRC('BULLCP',IER)
+
+	   IF (.NOT.IER) THEN
+	      CALL SYS_GETMSG(IER)
+	      CALL EXIT
+	   ELSE IF (JUST_STOP) THEN
+	      WRITE (6,'('' BULLCP process has been terminated.'')')
+	      CALL EXIT
+	   END IF
+	ELSE IF (JUST_STOP) THEN
+	   WRITE (6,'('' BULLCP is not presently running.'')')
+	   CALL EXIT
+	END IF
+
+	CALL GETIMAGE(IMAGENAME,ILEN)
+
+	LEN_B = TRIM(FOLDER_DIRECTORY)
+
+	CALL SYS$SETDFPROT('AA00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD:RW,GROUP:RW)
+C
+C  Generate a new BULLCP.COM each time.  This is done in case the BULLETIN
+C  executeable is moved, or a new version of BULLETIN is being installed that
+C  has changes to BULLCP.COM.  (It's also a security risk to execute the old
+C  copy, as someone might have been able to write into that directory and
+C  replace BULLCP.COM, and the command procedure is executed under the
+C  SYSTEM account, so it has all privileges.)
+C
+	OPEN(UNIT=11,FILE=FOLDER_DIRECTORY(:LEN_B)//'BULLCP.COM',
+     &		STATUS='NEW',IOSTAT=IER,CARRIAGECONTROL='LIST')
+	IF (IER.NE.0) RETURN
+	WRITE(11,'(A)') '$SET NOON'
+	WRITE(11,'(A)') '$B:=$'//IMAGENAME(:ILEN)
+	WRITE(11,'(A)') '$LOOP:'
+	WRITE(11,'(A)') '$PURGE '//FOLDER_DIRECTORY(:LEN_B)//'BULLCP.LOG'
+	WRITE(11,'(A)') '$DEF/USER SYS$OUTPUT '
+     &				//FOLDER_DIRECTORY(:LEN_B)//'BULLCP.LOG'
+	WRITE(11,'(A)') '$DEF/USER SYS$ERROR '
+     &				//FOLDER_DIRECTORY(:LEN_B)//'BULLCP.ERR'
+	WRITE(11,'(A)') '$B/BULLCP'
+	WRITE(11,'(A)') '$WAIT 00:01:00'
+	WRITE(11,'(A)') '$GOTO LOOP'		! File open timed out
+	CLOSE(UNIT=11)
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	CALL GETQUOTA(QUOTA,1)
+
+	IER = 0
+	DO WHILE (IER.EQ.0.OR.IER.EQ.SS$_DUPLNAM)
+	   IER = SYS$CREPRC(,'SYS$SYSTEM:LOGINOUT',FOLDER_DIRECTORY(:LEN_B)
+     &		//'BULLCP.COM','NL:',,,QUOTA,'BULLCP',%VAL(4),
+     &		,,%VAL(PRC$M_NOUAF+PRC$M_DETACH))
+	END DO
+
+	IF (IER) THEN
+	   OPEN(UNIT=11,FILE=FOLDER_DIRECTORY(:LEN_B)//'BULLCP.COM;-1',
+     &		STATUS='OLD',IOSTAT=IER1)
+	   IF (IER1.EQ.0) CLOSE(UNIT=11,STATUS='DELETE',IOSTAT=IER1)
+	END IF
+
+	IF (.NOT.IER) THEN
+	   CALL SYS_GETMSG(IER)
+	ELSE
+	   IF (CONFIRM_USER('DECNET').NE.0) THEN
+	      WRITE (6,'('' WARNING: Account with username DECNET'',
+     &				'' does not exist.'')')
+	      WRITE (6,'('' BULLCP will be owned by present account.'')')
+	   END IF
+	   WRITE (6,'('' Successfully created BULLCP detached process.'')')
+	END IF
+	CALL EXIT
+
+	END
+
+
+
+
+
+
+	SUBROUTINE FIND_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /BCP/ BULLCP
+	DATA BULLCP /0/
+
+	CHARACTER*80 TEMP
+
+	IER = SYS_TRNLNM('BULL_BULLCP',TEMP)
+	IF (IER.AND.TEMP.NE.'IGNORE') BULLCP = 1
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /BCP/ BULLCP
+	LOGICAL BULLCP
+
+	TEST_BULLCP = BULLCP
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE RUN_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BCP/ BULLCP
+	LOGICAL BULLCP
+
+	COMMON /KNOWN_FOLDERS/ FOLDER_Q1,NUM_FOLDERS
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /BBOARD_LOOP/ BBOARD_LOOP
+
+	CHARACTER*24 OLD_TIME,NEW_TIME
+
+        COMMON /MAIN_FOLDER_DIRECTORY/ FOLDER1_DIRECTORY
+	CHARACTER*80 FOLDER1_DIRECTORY
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	IF (TEST_BULLCP()) CALL EXIT	! BULLCP already running, so exit.
+
+	CALL LIB$DATE_TIME(OLD_TIME)
+
+	BULLCP = 2			! Enable process to do BULLCP functions
+
+	IER = SYS$CREMBX(%VAL(1),CHAN,,,,,'BULL_BULLCP')
+	IF (.NOT.IER) THEN		! Can't create mailbox, so exit.
+	   CALL SYS_GETMSG(IER)
+	   CALL EXIT
+	END IF
+
+	IER = SYS$DELMBX(%VAL(CHAN))	! If process dies, mailbox is deleted.
+
+	CALL REGISTER_BULLCP
+
+	CALL SET_REMOTE_SYSTEM
+
+	CALL START_DECNET
+
+	BBOARD_LOOP = 0
+	NEWS_LOOP = 0
+	NOW = SYS_TRNLNM('BULL_NEWS_CLEANUP','DEFINED')
+
+	DO WHILE (NEWS_LOOP.GE.0)		! Loop once every 15 minutes
+	   CALL SYS$SETAST(%VAL(0))
+
+	   UPDATEBBOARD = 1
+	   IF (SYS_TRNLNM('BULL_BBOARD_UPDATE',BULL_PARAMETER)) THEN
+	      LEN_P = TRIM(BULL_PARAMETER)
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER,IOSTAT=IER)
+     &		  UPDATEBBOARD
+	      IF (IER.EQ.0) UPDATEBBOARD = (UPDATEBBOARD+14) / 15
+	   END IF
+
+	   UPDATENEWS = 4
+	   IF (SYS_TRNLNM('BULL_NEWS_UPDATE',BULL_PARAMETER)) THEN
+	      LEN_P = TRIM(BULL_PARAMETER)
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER,IOSTAT=IER)
+     &		  UPDATENEWS
+	      IF (IER.EQ.0) UPDATENEWS = (UPDATENEWS+14) / 15
+	   END IF
+
+	   CALL LIB$DATE_TIME(NEW_TIME)
+	   CALL GET_PROXY_ACCOUNTS	! Proxy info for incoming connections
+	   FOLDER1_DIRECTORY = FOLDER_DIRECTORY
+	   CALL SYS$SETAST(%VAL(1))
+
+           IF (.NOT.NOW) NOW = INDEX(NEW_TIME,' 03:').NE.0.AND.
+     &                     INDEX(OLD_TIME,' 03:').EQ.0
+	   IER = 1
+	   DO WHILE (IER)
+	      CALL BBOARD			! Look for BBOARD messages.
+	      FOLDER_Q = FOLDER_Q1		! Init queue pointer to header
+	      POINT_FOLDER = 0
+	      DO WHILE (POINT_FOLDER.LT.NUM_FOLDERS)
+		 POINT_FOLDER = POINT_FOLDER + 1
+		 CALL SYS$SETAST(%VAL(0))
+		 CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+		 IF (FOLDER_BBOARD(:2).NE.'::') THEN
+		    CALL SELECT_FOLDER(.FALSE.,IER)	! Select folder
+		    IF (IER) THEN
+		       CALL DELETE_EXPIRED	! Delete expired messages
+		       IF (NOW) THEN	! Do empty block cleanup at 3 a.m.
+			  IF (NEMPTY.GT.1000.AND.NEMPTY.GT.NBLOCK/10) THEN
+			     CALL CLEANUP_BULLFILE	! Cleanup empty blocks
+			  END IF
+		       END IF
+		    END IF
+		 END IF
+	         IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+		    CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	         END IF
+		 CALL SYS$SETAST(%VAL(1))
+	      END DO
+	      IF (NOW) THEN  ! Cleanup deleted users from files at 3 a.m.
+	         CALL SYS$SETAST(%VAL(0))
+	         CALL TOTAL_CLEANUP_LOGIN
+	         CALL SYS$SETAST(%VAL(1))
+	      END IF
+	      CALL SYS$SETAST(%VAL(0))
+	      CALL REGISTER_BULLCP
+	      IER1 = 1
+	      DO WHILE (IER1)
+	         IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',
+     &			   FOLDER_DIRECTORY)
+	         IF (IER.AND.FOLDER_DIRECTORY.EQ.FOLDER1_DIRECTORY) THEN 
+		    IER1 = 1
+	         ELSE
+		    IER1 = 0
+		 END IF
+      	      END DO
+	      IF (IER) CALL ADD_DIRECTORIES
+	      CALL SYS$SETAST(%VAL(1))
+	   END DO
+
+           CALL SYS$SETAST(%VAL(0)) 
+	   FOLDER_DIRECTORY = FOLDER1_DIRECTORY
+           CALL ADD_DIRECTORIES
+           CALL SYS$SETAST(%VAL(1))
+
+	   BBOARD_LOOP = BBOARD_LOOP + 1
+	   IF (BBOARD_LOOP.EQ.UPDATEBBOARD) BBOARD_LOOP = 0
+
+	   CALL SYS$SETAST(%VAL(0))
+	   IF (SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED').AND.
+     &	      (NEWS_LOOP.EQ.0.OR.NOW)) THEN
+	      IF (NOW) THEN
+	         CALL CREATE_PROCESS('BULLCP NEWS1')
+	      ELSE
+	         CALL CREATE_PROCESS('BULLCP NEWS')
+	      END IF
+           END IF
+	   CALL SYS$SETAST(%VAL(1))
+
+	   C = 0
+	   IF (LIB$FIND_FILE(FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &			//'*.SMTP',INPUT,C)) THEN
+	      CALL CREATE_PROCESS('BULLCP SMTP')
+	   END IF
+
+	   NOW = .FALSE.
+
+	   NEWS_LOOP = NEWS_LOOP + 1
+	   IF (NEWS_LOOP.EQ.UPDATENEWS) NEWS_LOOP = 0
+
+	   OLD_TIME = NEW_TIME
+	   CALL HIBER('15')		! Wait for 15 minutes
+C
+C  Look at remote folders and update local info to reflect new messages.
+C  Do here after waiting in case problem with connecting to remote folder
+C  which requires killing process.
+C
+
+	   FOLDER_Q = FOLDER_Q1
+	   POINT_FOLDER = 0
+	   DO WHILE (POINT_FOLDER.LT.NUM_FOLDERS)
+	      POINT_FOLDER = POINT_FOLDER + 1
+	      CALL SYS$SETAST(%VAL(0))
+	      CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      IF (FOLDER_BBOARD(:2).EQ.'::') THEN
+		 CALL SELECT_FOLDER(.FALSE.,IER)
+	      END IF
+	      CALL SYS$SETAST(%VAL(1))
+	   END DO
+	   CALL SYS$SETAST(%VAL(0))
+	   FOLDER_NUMBER = 0			! Reset to GENERAL folder
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL SYS$SETAST(%VAL(1))
+	END DO
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE SET_REMOTE_SYSTEM
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	DIMENSION NEW_SYSTEM_FLAG(FLONG)
+
+	CALL LIB$SYS_TRNLOG('SYS$NODE',,NODENAME)
+	NODENAME = NODENAME(2:INDEX(NODENAME,':')-1)
+
+ 	CALL OPEN_BULLFOLDER_SHARED
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   CALL READ_FOLDER_FILE(IER)
+	   IF (BTEST(FOLDER_FLAG,2))
+     &		CALL SET2(NEW_SYSTEM_FLAG,FOLDER_NUMBER)
+	   IF (FOLDER_BBOARD(:2).EQ.'::'.AND.BTEST(FOLDER_FLAG,2)
+     &		.AND.IER.EQ.0) THEN
+	      CALL CLOSE_BULLFOLDER
+	      CALL SETUSER(FOLDER_OWNER)
+	      CALL SELECT_FOLDER(.FALSE.,IER1)
+	      IF (IER1) THEN
+	         WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER1) 14,
+     &			BTEST(FOLDER_FLAG,2),NODENAME
+	      END IF
+	      CALL SETUSER(USERNAME)
+ 	      CALL OPEN_BULLFOLDER_SHARED
+	      CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFOLDER
+
+	FOLDER_NUMBER = 0			! Reset to GENERAL folder
+	CALL SELECT_FOLDER(.FALSE.,IER)
+
+	FOLDER1_FLAG = FOLDER_FLAG
+	DO FOLDER_NUMBER=0,FOLDER_MAX-1
+	   IF (TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND..NOT.
+     &	       TEST2(NEW_SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,2)
+	      CALL MODIFY_SYSTEM_LIST(0)
+	   END IF
+	END DO
+	FOLDER_FLAG = FOLDER1_FLAG
+	FOLDER_NUMBER = 0
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE REGISTER_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INTEGER SHUTDOWN_BTIM(FLONG)
+
+	EQUIVALENCE (SHUTDOWN_BTIM,BRIEF_FLAG)
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER REGNODE*8
+
+	CALL OPEN_BULLUSER
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*SYSTEM',IOSTAT=IER) 
+     &		TEMP_USER,REGNODE,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END DO
+
+	CALL LIB$SYS_TRNLOG('SYS$NODE',,NODENAME)
+	NODENAME = NODENAME(2:INDEX(NODENAME,':')-1)
+
+	IF (IER.NE.0) THEN
+	   DO I=1,FLONG
+	      SYSTEM_FLAG(I) = 0
+	      SHUTDOWN_FLAG(I) = 0
+	   END DO
+	   CALL SET2(SYSTEM_FLAG,0)
+	   NODE_AREA = 0
+	   WRITE (4,IOSTAT=IER)
+     &		'*SYSTEM     ',NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	   CALL CLOSE_BULLUSER
+	ELSE
+	   DO I=1,FLONG
+	      SHUTDOWN_FLAG(I) = SYSTEM_FLAG(I)
+	   END DO
+	   REWRITE (4,IOSTAT=IER)
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+           IF (NODENAME.EQ.REGNODE) THEN
+	      CALL CLOSE_BULLUSER
+	      RETURN
+	   END IF
+	   TEMP_USER = ':'
+	   DO WHILE (TEMP_USER(:1).EQ.':')
+	      DO WHILE (REC_LOCK(IER))		 
+	         READ (4,KEYGT=TEMP_USER,IOSTAT=IER)
+     &		   TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+		 TEMP_USER = TEMP_USER(:TRIM(TEMP_USER))
+	      END DO
+	      IF (TEMP_USER(:1).NE.':'.OR.IER.NE.0) THEN
+		 CALL CLOSE_BULLUSER
+		 RETURN
+	      END IF
+	      OPEN (UNIT=REMOTE_UNIT,STATUS='UNKNOWN',IOSTAT=IER,RECL=256,
+     &		FILE=TEMP_USER(2:LEN(TEMP_USER))//'::"TASK=BULLETIN1"')
+
+	      IF (IER.NE.0) THEN
+		 CALL ERRSNS(IDUMMY,IDUMMY,INODE)
+	         IF (INODE.EQ.%LOC(SS$_NOSUCHNODE).OR.
+     &		     INODE.EQ.%LOC(SS$_NOSUCHOBJ).OR.INODE.EQ.0) THEN
+		    DELETE (4)
+		 END IF
+	      ELSE
+		 WRITE (REMOTE_UNIT,'(3A)',IOSTAT=IER)
+     &			16,REGNODE,NODENAME
+	      END IF
+	      CLOSE (UNIT=REMOTE_UNIT)
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE UPDATE_SHUTDOWN(FOLDER_NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INTEGER SHUTDOWN_BTIM(FLONG)
+
+	EQUIVALENCE (SHUTDOWN_BTIM,BRIEF_FLAG)
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	CALL OPEN_BULLUSER
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*SYSTEM',IOSTAT=IER) 
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END DO
+
+	CALL CLR2(SHUTDOWN_FLAG,FOLDER_NUMBER)
+
+	SEEN_FLAG = 0
+	DO I=1,FLONG
+	   IF (SHUTDOWN_FLAG(I).NE.0) SEEN_FLAG = 1
+	END DO
+	IF (SEEN_FLAG.EQ.0) NODE_AREA = 0	! All done with that node
+
+	IF (IER.NE.0) THEN
+	   WRITE (4,IOSTAT=IER)
+     &		'*SYSTEM     ',NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	ELSE
+	   REWRITE (4,IOSTAT=IER)
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE HIBER(MIN)
+C
+C SUBROUTINE HIBER
+C
+C FUNCTION: Waits for specified time period in minutes.
+C
+	IMPLICIT INTEGER (A-Z)
+	INTEGER TIMADR(2)			! Buffer containing time
+						! in desired system format.
+	CHARACTER MIN*(*)
+
+	IER=SYS$BINTIM('0 00:'//MIN//':00.00',TIMADR)
+	IER=SYS$SCHDWK(,,TIMADR,)		! Set timer.
+	IER=SYS$HIBER()
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE WAIT_SEC(PARAM)
+C
+C SUBROUTINE WAIT_SEC
+C
+C FUNCTION: Waits for specified time period in seconds.
+C
+	IMPLICIT INTEGER (A-Z)
+	INTEGER TIMADR(2)			! Buffer containing time
+						! in desired system format.
+	CHARACTER PARAM*(*)
+	DATA WAIT_EF /0/
+
+	IF (WAIT_EF.EQ.0) CALL LIB$GET_EF(WAIT_EF)
+
+	IER=SYS$BINTIM('0 00:00:'//PARAM//'.00',TIMADR)
+	IER=SYS$SETIMR(%VAL(WAIT_EF),TIMADR,,%VAL(3))	! Set timer.
+	IER=SYS$WAITFR(%VAL(WAIT_EF))		! Wait for EFN to be set.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELETE_EXPIRED_NEWS(NOW)
+C
+C  SUBROUTINE DELETE_EXPIRED_NEWS
+C
+C  FUNCTION:
+C
+C  Delete any expired message in local news folders.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+ 	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+        COMMON /BULLFIL/ BULLFIL
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+
+	COMMON /NEWSLIST/ NEWSLIST
+
+	COMMON /DIRLIST/ DIRLIST
+
+	CHARACTER*4 GET_VMS_VERSION
+
+	INTEGER TODAY(2),NEXT_EX_BTIM(2),NO_EXPIRE(2)
+
+	CHARACTER*8 TODAY_KEY,TEMP
+	CHARACTER ASCTIME*24
+
+	IF (.NOT.SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) RETURN
+
+	IF (NOW) THEN 
+       	   IER = SYS$SETPRN('BULL NEWS1')
+	   IF (.NOT.IER) CALL EXIT
+	   IER = SYS$SETPRN('BULL NEWS')
+	   IF (.NOT.IER) CALL EXIT
+	END IF
+
+	FOLDER_NUMBER = 1000
+
+	FOLDER_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY)-1)//'.]'
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1)
+	END DO
+
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLNEWS
+	   RETURN
+	END IF
+
+	CALL SYS_BINTIM('-',TODAY)
+	
+	CALL GET_MSGKEY(TODAY,TODAY_KEY)
+
+	REMOTE_SET = 4
+	
+C
+C	A bug keeps messing up the last expired date key so that stored
+C	news groups do not get found.  Someday when this is fixed, we can
+C	add code like this:
+C
+C	INPUT = GET_VMS_VERSION()
+C	IF (INPUT(:2).EQ.'V5'.OR.INPUT(:2).EQ.'V4') VMSOLD = .TRUE..AND.NOW
+
+	DO WHILE (IER.EQ.0)
+	   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NEXT_EX_BTIM)
+
+	   DO WHILE (REC_LOCK(IER).OR.(NOW.AND.IER.EQ.0.AND.
+     &		(.NOT.BTEST(NEWS_F_FLAG,8).OR.
+     &		 COMPARE_BTIM(TODAY,NEWEST_EXBTIM).LT.0)))
+	      IF (NOW) THEN
+	         READ (7,IOSTAT=IER) NEWS_FOLDER_COM
+	         CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),
+     &				 %DESCR(NEWEST_EXBTIM))
+	      ELSE
+	         READ (7,IOSTAT=IER,KEYLE=TODAY_KEY,KEYID=3) NEWS_FOLDER_COM
+	      END IF
+	   END DO
+	   CALL NEWS_TO_FOLDER
+
+	   UNLOCK 7
+
+	   IF (IER.NE.0) THEN
+	      CALL CLOSE_BULLNEWS
+	      GO TO 1000
+           END IF
+
+	   IF (.NOT.BTEST(FOLDER_FLAG,8)) GO TO 900
+
+	   CALL OPEN_BULLDIR_SHARED
+
+	   CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),%DESCR(NEWEST_EXBTIM))
+
+	   DEL_COUNT = 0
+	   NDEL = -1
+	   DS = .FALSE.
+	   DN = .FALSE.
+	   CALL READ_FIRST_EXPIRED(NDEL)
+	   DO WHILE (NDEL.GT.0)
+	      DIFF = COMPARE_BTIM(TODAY,EX_BTIM)
+	      IF (DIFF.GT.0) THEN
+	         IF (NDEL.EQ.F_START) DS = .TRUE.
+	         IF (NDEL.EQ.F_NBULL) DN = .TRUE.	
+                 IF (NDEL.GT.NEWS_F_END) THEN
+	            CALL READ_NEXT_EXPIRED(NDEL)
+		 ELSE IF (COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).GE.0) THEN
+      		    DEL_COUNT = DEL_COUNT + 1
+	            CALL READ_NEXT_EXPIRED(NDEL)
+	         ELSE IF (EXDATE(8:11).LT.'1995') THEN	! Deleted manually?
+	            IF (LENGTH.GT.0) CALL DUMP_MESSAGE()
+		    CALL SYS$ASCTIM(,ASCTIME,TODAY,)
+	            EXDATE = ASCTIME(:11) 
+		    EXTIME = ASCTIME(13:23)
+		    LENGTH = 0
+	      	    CALL WRITEDIR(MSG_NUM,IER)
+		    DEL_COUNT = 0
+	            CALL READ_FIRST_EXPIRED(NDEL)
+		 ELSE
+                    CALL READ_NEXT_EXPIRED(NDEL) 
+	         END IF
+	      ELSE
+		 CALL COPY2(NEXT_EX_BTIM,EX_BTIM)
+	         IF (F_COUNT.LE.DEL_COUNT.OR.NDEL.GT.NEWS_F_END) THEN
+		   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NEXT_EX_BTIM)
+		 END IF
+		 NDEL = 0
+                 UNLOCK 2
+ 	      END IF
+	   END DO
+	   CALL READ_FOLDER_FILE_KEYNAME(NEWS_FOLDER,IER)
+	   NEXT = .FALSE.
+	   CALL READDIR(F_START,IER)
+	   IF (DS.OR.F_START.EQ.IER) THEN
+	      IER = 0
+	      NEXT = .TRUE.
+              I = F_START
+              DO WHILE (F_NBULL.GE.I.AND.IER.EQ.0)
+		 I = I + 1
+		 IF (I.LE.F_NBULL) CALL READDIR(I,IER)
+		 IF (COMPARE_BTIM(EX_BTIM,NEXT_EX_BTIM).LT.0) IER = 0
+	      END DO
+              F_START = I
+	      NEXT = .FALSE.
+	   END IF
+	   CALL READDIR(F_NBULL,IER)
+	   IF (F_START.LT.F_NBULL.AND.(DN.OR.F_NBULL.EQ.IER)) THEN
+	      I = F_NBULL
+	      IER = I
+	      DO WHILE (I.GE.F_START.AND.IER.EQ.I)
+		 I = I - 1
+		 IF (I.GE.F_START) CALL READDIR(I,IER)
+		 IF (COMPARE_BTIM(EX_BTIM,NEXT_EX_BTIM).LT.0) IER = I
+	      END DO
+	      IF (I.GE.F_START) CALL COPY2(F_NEWEST_BTIM,MSG_BTIM)
+	      IF (I.NE.IER) F_NBULL = I
+	   END IF
+	   F_COUNT = MAX(0,F_COUNT - DEL_COUNT)
+	   CALL GET_MSGKEY(TODAY,NEWS_F_EXPIRED_DATE)
+	   FOLDER_FLAG = IBSET(FOLDER_FLAG,13)
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) THEN
+    	      CALL READ_FIRST_EXPIRED(NDEL)
+	      DO WHILE (NDEL.GT.0.AND.NDEL.LE.NEWS_F_END.AND.
+     &		COMPARE_BTIM(EX_BTIM,NEXT_EX_BTIM).LT.0)
+	         IF (LENGTH.GT.0) CALL DUMP_MESSAGE()
+	         DELETE (UNIT=2)
+    	         CALL READ_FIRST_EXPIRED(NDEL)
+	      END DO
+	      CALL READ_FOLDER_FILE_KEYNAME(NEWS_FOLDER,IER)
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,13)
+	      CALL GET_MSGKEY(NEXT_EX_BTIM,NEWS_F_EXPIRED_DATE)
+	      CALL REWRITE_FOLDER_FILE(IER)
+	   END IF
+           CALL CLOSE_BULLDIR
+	END DO
+
+900     CALL CLOSE_BULLNEWS
+
+1000	IF (NOW.OR.IER.EQ.0) THEN
+	   BULLNEWSDIR_FILE = FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWSDIR.*]'//'*.'
+	   INPUT = GET_VMS_VERSION()
+	   CALL LIB$DAY_OF_WEEK(TODAY,DAY)
+	   IF (DAY.NE.7) THEN
+	      IER = SYS_TRNLNM('BULL_NEWS_CLEANUP','DEFINED')
+	      IF (IER) THEN
+		 DAY = 7
+	         CALL DELLNM('BULL_NEWS_CLEANUP')
+	      END IF
+	   END IF
+	   IF (INPUT(:2).NE.'V5'.AND.INPUT(:2).NE.'V4') THEN
+	      CONTEXT = 0
+	      DO WHILE (LIB$FIND_FILE(BULLNEWSDIR_FILE,INPUT,CONTEXT))
+	         IER = CONV$RECLAIM(INPUT(:TRIM(INPUT)))
+	      END DO 
+	   ELSE IF (DAY.EQ.7) THEN
+	      REMOTE_SET = 4
+	      DIRLIST = .TRUE.
+	      NEWSLIST = .TRUE.
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL READ_FOLDER_FILE_KEYNUM(1000,IER)
+	      CALL READ_FOLDER_FILE(IER)
+	      CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NO_EXPIRE)
+	      DO WHILE (IER.EQ.0)
+	         UNLOCK 7
+		 CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),
+     &				 %DESCR(NEWEST_EXBTIM))
+		 IF (BTEST(FOLDER_FLAG,8)) THEN
+		    CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+		    C = 0
+	            IF (LIB$FIND_FILE(BULLNEWSDIR_FILE
+     &			(:TRIM(BULLNEWSDIR_FILE))//';1',INPUT,C)) THEN
+                       IER = LIB$DELETE_FILE(
+     &			BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))//';2')
+		    ELSE
+		       IER = LIB$RENAME_FILE(
+     &			BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE)),'*.*;1')
+		    END IF
+		    CALL OPEN_BULLDIR_SHARED
+		    OPEN (UNIT=9,FILE=BULLNEWSDIR_FILE,SHARED,
+     &	             BUFFERCOUNT=127,
+     &		     INITIALSIZE=(NEWSDIR_RECORD_LENGTH*F_COUNT)/512,
+     &	             STATUS='NEW',FORM='UNFORMATTED',DISPOSE='DELETE',
+     &	             RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,IOSTAT=IER,
+     &	             ORGANIZATION='INDEXED',RECORDTYPE='FIXED',
+     &	             KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	             57:64:CHARACTER),ACCESS='KEYED')
+		    IF (IER.NE.0) THEN
+		       CALL CLOSE_BULLDIR
+		       CALL CLOSE_BULLNEWS
+		       RETURN
+		    END IF
+		    DO WHILE (IER.EQ.0)
+		       DO WHILE (REC_LOCK(IER))
+		          READ (2,IOSTAT=IER) NEWSDIR_ENTRY
+		       END DO
+		       IF (IER.EQ.0) THEN
+			  WRITE (9,IOSTAT=IER) NEWSDIR_ENTRY
+			  IF (IER.NE.0) THEN
+			     CALL CLOSE_BULLDIR
+			     CALL CLOSE_BULLNEWS
+		             RETURN
+			  ELSE
+	     		     CALL GET_MSGKEY(%REF(NEWS_EX_BTIM_KEY),
+     &					     %DESCR(EX_BTIM))
+			     IF (COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).LT.0)
+     &			        CALL COPY2(NEWEST_EXBTIM,EX_BTIM)
+		          END IF
+		       END IF
+		    END DO
+		    CLOSE (UNIT=9,DISPOSE='KEEP')
+		    CALL CLOSE_BULLDIR_DELETE
+		    CALL GET_MSGKEY(NEWEST_EXBTIM,TEMP)
+		    IF (TEMP.NE.NEWS_F_EXPIRED_DATE) THEN 
+		       CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+		       NEWS_F_EXPIRED_DATE = TEMP
+	               CALL REWRITE_FOLDER_FILE(IER)
+		       CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+		    END IF
+		    IER = LIB$RENAME_FILE(
+     &			BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE)),'*.*;1')
+		 ELSE
+		    IF (NO_EXPIRE(1).NE.NEWEST_EXBTIM(1).OR.
+     & 			NO_EXPIRE(2).NE.NEWEST_EXBTIM(2)) THEN
+		       CALL GET_MSGKEY(NO_EXPIRE,NEWS_F_EXPIRED_DATE)
+	               CALL REWRITE_FOLDER_FILE(IER)
+		       CALL OPEN_BULLDIR
+		       CALL CLOSE_BULLDIR_DELETE
+		    ELSE 
+		       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+		    END IF
+		    IER = 1
+		    DO WHILE (IER)
+                      IER = LIB$DELETE_FILE(
+     &			 BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))//';')
+	            END DO
+		 END IF
+	         CALL READ_FOLDER_FILE(IER)
+	      END DO
+	      CALL CLOSE_BULLNEWS
+	   END IF
+	   DIRLIST = .FALSE.
+	   NEWSLIST = .TRUE.
+	   CALL COPY2(EX_BTIM,TODAY)
+           BULLFIL = 0
+	   IER = .TRUE.
+	   DO WHILE (IER)
+	      IER = SYS_BINTIM('1 00:00',DAY)
+	      IER = LIB$ADDX(EX_BTIM,DAY,EX_BTIM)
+	      CALL SET_BULLFIL
+	      IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &			'.BULLFIL;')
+	      IER = INDEX(FOLDER_FILE,']1JAN').EQ.0
+	   END DO
+	   J = INDEX(FOLDER_FILE,']')
+	   DECODE(2,'(I2)',FOLDER_FILE(J-2:J-1),IOSTAT=IER) YEAR
+	   IF (IER.EQ.0) THEN 
+	      DO I=1,10
+	         YEAR = YEAR - 1
+	         IF (YEAR.EQ.-1) YEAR = 99
+	         ENCODE(2,'(I2)',FOLDER_FILE(J-2:J-1),IOSTAT=IER) YEAR
+                 IF (IER.EQ.0) IER = LIB$DELETE_FILE(FOLDER_FILE(:J)
+     &                  //'*.*;*')
+	      END DO
+	   END IF
+           IER = LIB$DELETE_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &                  //'BULLNEWS*.DIR;*')
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELETE_EXPIRED
+C
+C  SUBROUTINE DELETE_EXPIRED
+C
+C  FUNCTION:
+C
+C  Delete any expired bulletins (normal or shutdown ones).
+C  (NOTE: If bulletin files don't exist, they get created now by
+C  OPEN_FILE_SHARED.  Also, if new format has been defined for files,
+C  they get converted now.  The directory file has had it's record size
+C  lengthened in the past to include more info, and the bulletin file 
+C  was lengthened from 80 to 81 characters to include byte which indicated
+C  start of bulletin message.  However, that scheme was removed and
+C  was replaced with a 128 byte record compressed format).
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	CALL OPEN_BULLDIR_SHARED	! Open directory file
+	CALL OPEN_BULLFIL_SHARED	! Open bulletin file
+	CALL CLOSE_BULLFIL
+	CALL READDIR(0,IER)		! Get directory header
+	IF (IER.EQ.1) THEN		! Is header present?
+	   IER = COMPARE_DATE(NEWEST_EXDATE,' ') ! Yes. Any expired bulls?
+	   IF (IER.GT.20*356) IER = -1	! Check if latest expiration date valid.
+	   IF (IER.EQ.0) IER = COMPARE_TIME(NEWEST_EXTIME,' ')
+	   IF (SHUTDOWN.GT.0.AND.NODE_AREA.GT.0.AND.
+     &		(FOLDER_NUMBER.EQ.0.OR.BTEST(FOLDER_FLAG,2)).AND.
+     &		TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+			! Do shutdown messages exist and need to be checked?
+	      SHUTDOWN = 0
+	      IER1 = -1
+	   ELSE
+	      IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+		 CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	      END IF
+	      IER1 = 1
+	   END IF
+	   IF (IER.LE.0.OR.IER1.LE.0) THEN
+	      CALL CLOSE_BULLDIR
+	      CALL OPEN_BULLDIR		! Reopen without sharing
+	      CALL UPDATE 		! Need to update
+	   END IF
+	ELSE		! If header not there, then first time running BULLETIN
+	   IF (FOLDER_NUMBER.EQ.0) THEN
+	      CALL OPEN_BULLUSER	! Create user file to be able to set
+	      CALL CLOSE_BULLUSER	! defaults, privileges, etc.
+	   END IF
+           IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+              CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+           END IF
+	END IF
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE BBOARD
+C
+C  SUBROUTINE BBOARD
+C
+C  FUNCTION: Converts mail to BBOARD into non-system bulletins.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /KNOWN_FOLDERS/ FOLDER_Q1,NUM_FOLDERS
+	DATA FOLDER_Q1/0/
+
+	COMMON /BBOARD_LOOP/ BBOARD_LOOP
+
+	COMMON /MAIL_INFO/ USE_INFROM
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+
+	CHARACTER*12 INEXDATE
+	CHARACTER INDESCRIP*(INPUT_LENGTH),INFROM*(INPUT_LENGTH),INTO*76
+	CHARACTER ACCOUNT_SAVE*8,USERNAME_SAVE*12
+	CHARACTER F_BBOARD*64,BBOARD_NAME*64
+
+	DIMENSION NEW_MAIL(FOLDER_MAX)
+
+	DATA SPAWN_EF/0/
+
+	CALL SYS$SETAST(%VAL(0))
+
+	IF (SPAWN_EF.EQ.0) CALL LIB$GET_EF(SPAWN_EF)
+
+	CALL DISABLE_CTRL
+
+	CALL INIT_QUEUE(FOLDER_Q1,FOLDER_COM)
+
+	FOLDER_Q = FOLDER_Q1
+
+	CALL OPEN_BULLFOLDER_SHARED		! Get folder file
+
+	NUM_FOLDERS = 0
+	IER = 0
+	DO WHILE (IER.EQ.0)			! Copy all bulletins from file
+	   CALL READ_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) THEN
+	      NUM_FOLDERS = NUM_FOLDERS + 1
+	      CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFOLDER			! We don't need file anymore
+	CALL SYS$SETAST(%VAL(1))
+
+	IF (TEST_BULLCP().EQ.2.AND.BBOARD_LOOP.NE.0) GO TO 900
+
+	CALL SYS$SETAST(%VAL(0))
+	CALL CHECK_MAIL(NEW_MAIL)
+	CALL SYS$SETAST(%VAL(1))
+
+	FOLDER_Q = FOLDER_Q1			! Init queue pointer to header
+
+	NBBOARD_FOLDERS = 0
+
+	POINT_FOLDER = 0
+
+1	POINT_FOLDER = POINT_FOLDER + 1
+	IF (POINT_FOLDER.GT.NUM_FOLDERS) GO TO 900
+
+	CALL SYS$SETAST(%VAL(0))
+
+	FOLDER_Q_SAVE = FOLDER_Q
+
+	CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+
+	IF (FOLDER_BBOARD(:4).EQ.'NONE'.OR.
+     &		FOLDER_BBOARD(:2).EQ.'::') GO TO 1
+
+	NBBOARD_FOLDERS = NBBOARD_FOLDERS + 1
+
+	IF (.NOT.NEW_MAIL(POINT_FOLDER)) GO TO 1
+C
+C  The process is set to the BBOARD uic and username in order to create
+C  a spawned process that is able to read the BBOARD mail (a real kludge).
+C
+
+	CALL GETUSER(USERNAME_SAVE)		! Get present username
+	CALL GETACC(ACCOUNT_SAVE)		! Get present account
+	CALL GETUIC(GROUP_SAVE,USER_SAVE)	! Get present uic
+
+	IF (TRIM(FOLDER_BBOARD).GT.0) THEN	! BBOARD name present?
+	   IER = SETUSER(FOLDER_BBOARD,USERNAME_SAVE)! Set to BBOARD username
+	   IF (IER.EQ.2) GO TO 910	! Can't set username. New VMS version?
+	   CALL SETACC(ACCOUNTB)	! Set to BBOARD account
+	   CALL SETUIC(IBCLR(GROUPB,31),IBCLR(USERB,31)) ! Set to BBOARD uic
+	END IF
+
+	LEN_B = TRIM(BBOARD_DIRECTORY)
+	IER = LIB$DELETE_FILE(BBOARD_DIRECTORY(:LEN_B)//
+     &		FOLDER_BBOARD(:TRIM(FOLDER_BBOARD))//'.TXT;*')
+				! Delete old TXT files left due to errors
+
+	IF (.NOT.BTEST(USERB,31).AND.(USERB.NE.0.OR.GROUPB.NE.0)) THEN
+	      						! If normal BBOARD user
+	   IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)
+     &		  //'READ_BOARD.COM','NL:','NL:',1,,,STATUS,SPAWN_EF)
+	   CALL SYS$SETAST(%VAL(1))
+	   IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	   CALL SYS$SETAST(%VAL(0))
+	   IF (((STATUS.AND.'1FFFF'X).EQ.RMS$_FNF) .OR.
+     &	    ((STATUS .AND. '1FFF0'X).EQ. (RMS$_SPL .AND. '1FFF0'X))) THEN
+	      CALL SYS$SETDFPROT('AA00'X,CUR_DEF_PROT)
+	      	! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD:RW,GROUP:RW)
+	      OPEN(UNIT=11,FILE=BBOARD_DIRECTORY(:LEN_B)//'READ_BOARD.COM',
+     &		   STATUS='NEW',ERR=910,CARRIAGECONTROL='LIST')
+	      WRITE(11,'(A)') '$ SET PROTECT=(W:RWED)/DEFAULT'
+	      WRITE(11,'(A)') '$ SET PROC/PRIV=SYSPRV'
+	      WRITE(11,'(A)')
+     &	       '$ DEFINE/USER EXTRACT_FILE '//BBOARD_DIRECTORY(:LEN_B)//
+     &	       '''F$GETJPI("","USERNAME")'''
+	      WRITE(11,'(A)') '$ MAIL'
+	      WRITE(11,'(A)') 'SELECT MAIL'
+	      WRITE(11,'(A)') 'READ'
+	      WRITE(11,'(A)') 'EXTRACT/ALL/APPEND EXTRACT_FILE'
+	      WRITE(11,'(A)') 'DELETE/ALL'
+	      WRITE(11,'(A)') 'READ/NEW'
+	      WRITE(11,'(A)') 'EXTRACT/ALL/APPEND EXTRACT_FILE'
+	      WRITE(11,'(A)') 'DELETE/ALL'
+	      WRITE(11,'(A)') 'SELECT/NEW'
+	      CLOSE(UNIT=11)
+	      CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+	      IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)
+     &		   //'READ_BOARD.COM','NL:','NL:',1,,,STATUS,SPAWN_EF)
+	      CALL SYS$SETAST(%VAL(1))
+	      IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	      CALL SYS$SETAST(%VAL(0))
+	   END IF
+	ELSE
+	   CONTEXT = 0
+	   IER = LIB$FIND_FILE(BBOARD_DIRECTORY(:LEN_B)//FOLDER_BBOARD
+     &	      (:TRIM(FOLDER_BBOARD))//'.COM',INPUT,CONTEXT)
+	   IF (IER) THEN
+	      IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)//
+     &		  FOLDER_BBOARD(:TRIM(FOLDER_BBOARD))//'.COM','NL:',
+     &		  'NL:',1,,,STATUS,SPAWN_EF)
+	      CALL SYS$SETAST(%VAL(1))
+	      IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	      CALL SYS$SETAST(%VAL(0))
+	   END IF
+	   IF (.NOT.IER.OR.((STATUS.AND.'1FFFF'X).EQ.RMS$_FNF) .OR.
+     &	    ((STATUS .AND. '1FFF0'X).EQ. (RMS$_SPL .AND. '1FFF0'X))) THEN
+	      IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)//
+     &		'BOARD_SPECIAL.COM','NL:','NL:',1,,,STATUS,SPAWN_EF)
+	      CALL SYS$SETAST(%VAL(1))
+	      IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	      CALL SYS$SETAST(%VAL(0))
+	   END IF
+	END IF
+
+	CALL READ_QUEUE(%VAL(FOLDER_Q_SAVE),FOLDER_Q,FOLDER_COM)
+
+	NBULL = F_NBULL
+
+	CALL SETACC(ACCOUNT_SAVE)		! Reset to original account
+	CALL SETUSER(USERNAME_SAVE)		! Reset to original username
+	CALL SETUIC(GROUP_SAVE,USER_SAVE)	! Reset to original uic
+
+	OPEN (UNIT=14,FILE=BBOARD_DIRECTORY(:LEN_B)//FOLDER_BBOARD
+     &	   (:TRIM(FOLDER_BBOARD))//'.TXT',STATUS='OLD',ERR=100)
+	READ (14,'(Q,A)',END=100) LEN_INPUT,INPUT ! Read first line
+	CALL SYS$SETAST(%VAL(1))
+
+5	CALL SYS$SETAST(%VAL(0))
+
+	CALL READ_QUEUE(%VAL(FOLDER_Q_SAVE),IDUMMY,FOLDER_COM)
+
+	DO WHILE (LEN_INPUT.GT.0)
+	   IF (INPUT(:5).EQ.'From:') THEN
+	      INFROM = INPUT(7:)		! Store username
+	   ELSE IF (INPUT(:5).EQ.'Subj:') THEN
+	      INDESCRIP = INPUT(7:)		! Store subject
+	   ELSE IF (INPUT(:3).EQ.'To:') THEN
+	      INTO = INPUT(5:)			! Store address
+	   END IF
+	   READ (14,'(Q,A)',END=100) LEN_INPUT,INPUT ! Read next line from mail
+	END DO
+
+	INTO = INTO(:TRIM(INTO))
+	CALL STR$TRIM(INTO,INTO)
+	CALL STR$UPCASE(INTO,INTO)
+	FLEN = TRIM(FOLDER_BBOARD)
+
+	IER = 0
+	CALL STRIP_HEADER(' ',-1,STRIP)
+	STRIP = .TRUE.
+	DO WHILE (IER.EQ.0.AND.STRIP)
+	   READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   IF (IER.EQ.0) THEN
+	      CALL STRIP_HEADER(INPUT,LEN_INPUT,STRIP)
+	      IF (STRIP.AND.INPUT(:5).EQ.'From:') INFROM = ' '
+	   END IF
+	END DO
+
+C
+C  If more than one folder has same BBOARD account, don't use the 
+C  To: line to determine which folder to put the mail message in.
+C
+	POINT_FOLDER1 = 0
+	FOLDER_Q2 = FOLDER_Q1
+	DUP = .FALSE.
+	DO WHILE (.NOT.DUP.AND.POINT_FOLDER1.LT.NUM_FOLDERS)
+	   CALL READ_QUEUE(%VAL(FOLDER_Q2),FOLDER_Q2,FOLDER1_COM)
+	   POINT_FOLDER1 = POINT_FOLDER1 + 1
+	   DUP = FOLDER.NE.FOLDER1.AND.FOLDER_BBOARD.EQ.FOLDER1_BBOARD
+	END DO
+	IF (DUP.OR..NOT.DETECT_BBOARD(INTO,FOLDER_BBOARD(:FLEN))) THEN
+	   FOUND = .FALSE.
+	   J = 0
+	   IF (DUP) J = 1
+	   DO WHILE (J.LT.2.AND..NOT.FOUND)
+	      J = J + 1
+	      POINT_FOLDER1 = 0
+	      FOLDER_Q2 = FOLDER_Q1
+	      FOUND = .FALSE.
+	      DO WHILE (.NOT.FOUND.AND.POINT_FOLDER1.LT.NUM_FOLDERS)
+		 CALL READ_QUEUE(%VAL(FOLDER_Q2),FOLDER_Q2,FOLDER1_COM)
+		 POINT_FOLDER1 = POINT_FOLDER1 + 1
+		 IF (POINT_FOLDER1.LE.NUM_FOLDERS.AND.
+     &		     FOLDER1_BBOARD(:2).NE.'::'.AND.
+     &		     FOLDER1_BBOARD(:4).NE.'NONE') THEN
+		    IF (J.EQ.1) THEN
+		       F_BBOARD = FOLDER1_BBOARD
+		       FOUND = INTO.EQ.F_BBOARD
+		    ELSE
+		       F_BBOARD = BBOARD_NAME(FOLDER1_BBOARD,FOLDER1_DESCRIP)
+		       FOUND = DETECT_BBOARD(INTO,F_BBOARD(:FLEN))
+		    END IF
+		    FLEN = TRIM(F_BBOARD)
+		    IF (.NOT.FOUND.AND.NHEAD.GT.1) THEN
+		       HEADER_Q = HEADER_Q1
+		       I = 1
+		       DO WHILE (I.LT.NHEAD.AND..NOT.FOUND)
+			  CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+			  FOUND = DETECT_BBOARD(INPUT,F_BBOARD(:FLEN))
+			  I = I + 1
+		       END DO
+		    END IF
+		 END IF
+	      END DO
+	   END DO
+	   IF (FOUND) FOLDER_COM = FOLDER1_COM
+	END IF
+
+	NUMHEAD = 0
+	IF (NHEAD.GT.0) NUMHEAD = NHEAD + 1
+
+	IF (NUMHEAD.GT.0) THEN
+	   HEADER_Q = HEADER_Q1
+	   CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+	   LEN_INPUT = TRIM(INPUT)
+	   NUMHEAD = NUMHEAD - 1
+	END IF
+
+	DO WHILE (LEN_INPUT.EQ.1.AND.INPUT(:1).EQ.CHAR(12).AND.IER.EQ.0)
+	   READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   IF (INPUT(:5).EQ.'From:') GO TO 5
+	END DO		! If line is just form feed, the message is empty
+	IF (IER.NE.0) GO TO 100				! If end of file, exit
+
+	EFROM = 2
+	I = TRIM(INFROM)
+	DO WHILE (EFROM.GT.0.AND.I.GT.0)		! Strip off the date
+	   IF (INFROM(I:I).EQ.' ') EFROM = EFROM - 1	! From the "From:" line
+	   I = I - 1
+	END DO
+	IF (I.GT.0) INFROM = INFROM(:I)
+
+	FOLDER_NAME = FOLDER			! For broadcasts
+
+	SAVE_Q = HEADER_Q
+	SAVE_Q1 = HEADER_Q1
+	NHEAD1 = NHEAD
+	HEADER_Q1 = 0
+		! INIT_MESSAGE_ADD_BBOARD reinits header so save it
+	CALL INIT_MESSAGE_ADD_BBOARD(INFROM,INDESCRIP,IER)
+
+	ISTART = 0
+	NBLANK = 0
+	IER = 0
+	DO WHILE (IER.EQ.0)		! Move text to bulletin file
+	   IF (LEN_INPUT.EQ.0) THEN
+	      IF (ISTART.EQ.1) THEN
+		 NBLANK = NBLANK + 1
+	      END IF
+	   ELSE
+	      ISTART = 1
+	      DO I=1,NBLANK
+		 CALL WRITE_MESSAGE_LINE(' ')
+	      END DO
+	      NBLANK = 0
+	      CALL WRITE_MESSAGE_LINE(INPUT)
+	   END IF
+	   IF (NUMHEAD.EQ.0) THEN
+	      READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   ELSE IF (NUMHEAD.EQ.1) THEN
+	      INPUT = ' '
+	      LEN_INPUT = 1
+	      NUMHEAD = NUMHEAD - 1
+	   ELSE
+	      CALL READ_QUEUE(%VAL(SAVE_Q),SAVE_Q,INPUT)
+	      LEN_INPUT = TRIM(INPUT)
+	      NUMHEAD = NUMHEAD - 1
+	   END IF
+	   IF (LEN_INPUT.EQ.1.AND.INPUT(:1).EQ.CHAR(12)) THEN
+	      DO WHILE (LEN_INPUT.EQ.1.AND.INPUT(:1).EQ.CHAR(12)
+     &			.AND.IER.EQ.0)
+		 READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	      END DO
+	      IF (IER.EQ.0.AND.INPUT(:5).EQ.'From:') THEN
+		 IER = 1
+	      ELSE
+		 NBLANK = NBLANK + 1
+	      END IF
+	   END IF
+	END DO
+
+	USE_INFROM = .TRUE.
+
+	NHEAD = NHEAD1
+	HEADER_Q1 = SAVE_Q1
+
+	CALL FINISH_MESSAGE_ADD			! Totally finished with add
+
+	CALL SYS$SETAST(%VAL(1))
+
+	GO TO 5					! See if there is more mail
+
+100	CLOSE (UNIT=14,STATUS='DELETE')		! Close the input file
+	CALL SYS$SETAST(%VAL(1))
+	GO TO 1
+
+900	CALL SYS$SETAST(%VAL(0))
+
+	FOLDER_NUMBER = 0
+	CALL OPEN_BULLFOLDER_SHARED
+	CALL READ_FOLDER_FILE_KEYNUM(0,IER)
+	CALL CLOSE_BULLFOLDER
+	CALL ENABLE_CTRL
+	FOLDER_SET = .FALSE.
+
+	IF (NBBOARD_FOLDERS.EQ.0) THEN
+	   CALL OPEN_BULLUSER
+	   CALL READ_USER_FILE_HEADER(IER)
+	   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',BBOARD_BTIM)
+	   REWRITE (4) USER_HEADER		! Rewrite header
+	   CALL CLOSE_BULLUSER
+	END IF
+	CALL SYS$SETAST(%VAL(1))
+
+	CALL SYS$SETAST(%VAL(0))
+	IF (SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) THEN
+	   CALL SYS$SETAST(%VAL(1))
+	   IF (.NOT.TEST_BULLCP().AND.TEST_BULLCP().NE.2)
+     &		CALL NEWS2BULL(.FALSE.)
+	END IF
+	CALL SYS$SETAST(%VAL(1))
+
+	RETURN
+
+910	WRITE (6,1010)
+	GO TO 100
+
+1010	FORMAT(' ERROR:Install program with CMKRNL privileges or relink.')
+
+	END
+
+
+
+
+	LOGICAL FUNCTION DETECT_BBOARD(INPUT,BBOARD)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,BBOARD
+
+	DETECT_BBOARD = .TRUE.
+
+	LEN_BBOARD = LEN(BBOARD) - 1
+	LEN_INPUT = TRIM(INPUT)
+
+	DO I=1,LEN_INPUT-LEN_BBOARD
+	   IF (.NOT.STREQ(INPUT(:4),'Subj').AND.
+     &		STREQ(INPUT(I:I+LEN_BBOARD),BBOARD).AND.
+     &		(I.EQ.1.OR..NOT.ALPHA(INPUT(I-1:I-1))).AND.
+     &		(I.EQ.LEN_INPUT-LEN_BBOARD.OR.
+     &		(INDEX('@%!',INPUT(I+LEN_BBOARD+1:I+LEN_BBOARD+1)).GT.0
+     &		.AND.(I.EQ.1.OR.(INPUT(I-1:I-1).NE.
+     &		INPUT(I+LEN_BBOARD+1:I+LEN_BBOARD+1).AND.
+     &		(INPUT(I-1:I-1).NE.'('.OR.
+     &		INPUT(I+LEN_BBOARD+1:I+LEN_BBOARD+1).NE.' ')))))) RETURN
+	END DO
+
+	DETECT_BBOARD = .FALSE.
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION ALPHA(IN)
+
+	CHARACTER*(*) IN
+
+	ALPHA = (ICHAR(IN).GE.ICHAR('A').AND.ICHAR(IN).LE.ICHAR('Z'))
+     &	    .OR.(ICHAR(IN).GE.ICHAR('a').AND.ICHAR(IN).LE.ICHAR('z'))
+
+	RETURN
+	END
+
+
+
+	CHARACTER*(*) FUNCTION BBOARD_NAME(FOLDER_BBOARD,FOLDER_DESCRIP)
+
+	CHARACTER*(*) FOLDER_BBOARD,FOLDER_DESCRIP
+
+	BBOARD_NAME = FOLDER_BBOARD
+
+	I = INDEX(FOLDER_DESCRIP,'<')
+	IF (I.EQ.0) RETURN
+
+	BBOARD_NAME = FOLDER_DESCRIP(I+1:)
+
+	I = INDEX(BBOARD_NAME,'%"')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(I+2:)
+
+	I = INDEX(BBOARD_NAME,'!')
+	DO WHILE (I.GT.0)
+	   BBOARD_NAME = BBOARD_NAME(I+1:)
+	   I = INDEX(BBOARD_NAME,'!')
+	END DO
+
+	I = INDEX(BBOARD_NAME,'>')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(:I-1)
+	I = INDEX(BBOARD_NAME,'@')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(:I-1)
+	I = INDEX(BBOARD_NAME,'%')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(:I-1)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CREATE_PROCESS(COMMAND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRCDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	LOGICAL*1 QUOTA(32)
+
+	CHARACTER*132 IMAGENAME
+
+	CHARACTER*(*) COMMAND
+
+	CALL GETIMAGE(IMAGENAME,ILEN)
+
+	LEN_B = TRIM(BBOARD_DIRECTORY)
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   OPEN(UNIT=11,FILE=BBOARD_DIRECTORY(:LEN_B)//'BULL_COMMAND.COM',
+     &		STATUS='OLD',IOSTAT=IER)
+	   IF (IER.EQ.0) CLOSE(UNIT=11,STATUS='DELETE')
+	END DO
+
+	CALL SYS$SETDFPROT('AA00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD:RW,GROUP:RW)
+	OPEN(UNIT=11,FILE=BBOARD_DIRECTORY(:LEN_B)//'BULL_COMMAND.COM',
+     &		STATUS='NEW',IOSTAT=IER,CARRIAGECONTROL='LIST')
+	IF (IER.NE.0) RETURN
+	IF (INDEX(IMAGENAME,';').GT.0) ILEN = INDEX(IMAGENAME,';')
+	WRITE(11,'(A)') '$B:=$'//IMAGENAME(:ILEN)
+	WRITE(11,'(A)') '$ON ERROR THEN GOTO EXIT'
+	WRITE(11,'(A)') '$ON SEVERE THEN GOTO EXIT'
+	WRITE(11,'(A)') '$ON WARNING THEN GOTO EXIT'
+	WRITE(11,'(A)') '$B/'//'''F$PROCESS()'''
+	WRITE(11,'(A)') '$EXIT:'
+	WRITE(11,'(A)') '$LOGOUT'
+	CLOSE(UNIT=11)
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	DEL = .FALSE.
+	IER = .FALSE.
+
+	CALL GETQUOTA(QUOTA,0)
+
+	DO WHILE (.NOT.IER)
+	   IER = SYS$CREPRC(,'SYS$SYSTEM:LOGINOUT',
+     &	    BBOARD_DIRECTORY(:LEN_B)//'BULL_COMMAND.COM','NL:',,
+     &	    PROCPRIV,QUOTA,COMMAND(:TRIM(COMMAND))
+     &	    ,%VAL(4),,,%VAL(PRC$M_NOUAF+PRC$M_DETACH))
+	   IF (.NOT.IER.AND..NOT.DEL) THEN
+	      CALL DELPRC('BULLCP NEWS',DEL)
+	      IER = .NOT.DEL
+	   ELSE
+	      IER = .TRUE.
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GETQUOTA(QUOTA,CLI)
+C
+C  SUBROUTINE GETQUOTA
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PQLDEF)'
+
+	INCLUDE '($JPIDEF)'
+                              
+	LOGICAL*1 QUOTA(32)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,JPI$_DFWSCNT,%LOC(WSDEFAULT))
+	CALL ADD_2_ITMLST(4,JPI$_WSEXTENT,%LOC(WSEXTENT))
+	CALL ADD_2_ITMLST(4,JPI$_WSQUOTA,%LOC(WSQUOTA))
+	CALL ADD_2_ITMLST(4,JPI$_BYTLM,%LOC(BYTLM))
+	CALL ADD_2_ITMLST(4,JPI$_ENQLM,%LOC(ENQLM))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)	! Get Info command.
+
+	I = 1
+	IF (CLI) THEN
+	   IF (CLI$GET_VALUE('PGFLQUOTA',BULL_PARAMETER,LEN_P)) THEN 
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) PGFLQUOTA
+	      QUOTA(1) = PQL$_PGFLQUOTA
+	      CALL LIB$MOVC3(4,PGFLQUOTA,QUOTA((I-1)*5+2))
+	      I = I + 1
+	   END IF
+	   IF (CLI$GET_VALUE('WSEXTENT',BULL_PARAMETER,LEN_P)) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) WSEXTENT
+	   END IF
+	END IF
+ 	QUOTA((I-1)*5+1) = PQL$_WSEXTENT
+	CALL LIB$MOVC3(4,WSEXTENT,QUOTA((I-1)*5+2)) 
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_WSQUOTA
+	CALL LIB$MOVC3(4,WSQUOTA,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_WSDEFAULT
+	CALL LIB$MOVC3(4,WSDEFAULT,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_BYTLM
+	CALL LIB$MOVC3(4,BYTLM,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_ENQLM
+	CALL LIB$MOVC3(4,ENQLM,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_LISTEND
+	CALL LIB$MOVC3(4,0,QUOTA((I-1)*5+2))
+
+        RETURN
+	END
+	
+
+
+
+	SUBROUTINE GETUIC(GRP,MEM)
+C
+C  SUBROUTINE GETUIC(UIC)
+C
+C  FUNCTION:
+C	To get UIC of process submitting the job.
+C  OUTPUT:
+C	GRP   -    Group number of UIC
+C	MEM   -	   Member number of UIC
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,JPI$_GRP,%LOC(GRP))
+	CALL ADD_2_ITMLST(4,JPI$_MEM,%LOC(MEM))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)	! Get Info command.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_UPTIME(UPTIME_DATE,UPTIME_TIME)
+C
+C  SUBROUTINE GET_UPTIME
+C
+C  FUNCTION: Gets time of last reboot.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	INTEGER 	UPTIME(2)
+	CHARACTER*(*)	UPTIME_TIME,UPTIME_DATE
+	CHARACTER	ASCSINCE*24
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(8,SYI$_BOOTTIME,%LOC(UPTIME))
+	CALL END_ITMLST(GETSYI_ITMLST)
+
+	IER = SYS$GETSYI(,,,%VAL(GETSYI_ITMLST),,,)
+
+	CALL SYS$ASCTIM(,ASCSINCE,UPTIME,)
+
+	UPTIME_DATE = ASCSINCE(:11)
+	UPTIME_TIME = ASCSINCE(13:23)
+
+	RETURN	
+	END
+
+
+
+	CHARACTER*4 FUNCTION GET_VMS_VERSION
+C
+C  FUNCTION GET_VMS_VERSION
+C
+C  FUNCTION: Gets VMS version 
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	CHARACTER VERSION*4
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(4,SYI$_NODE_SWVERS,%LOC(VERSION))
+	CALL END_ITMLST(GETSYI_ITMLST)
+
+	IER = SYS$GETSYI(,,,%VAL(GETSYI_ITMLST),,,)
+
+	GET_VMS_VERSION = VERSION
+
+	RETURN	
+	END
+
+
+
+	INTEGER FUNCTION GET_L_VAL(I)
+	INTEGER I
+	GET_L_VAL = I
+	RETURN
+	END
+
+
+
+	SUBROUTINE CHECK_MAIL(NEW_MAIL)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /KNOWN_FOLDERS/ FOLDER_Q1,NUM_FOLDERS
+	DATA FOLDER_Q1/0/
+
+	DIMENSION NEW_MAIL(1)
+
+	CHARACTER INPUT*132
+
+	INTEGER*2 COUNT
+
+	FOLDER_Q = FOLDER_Q1			! so reinit queue pointer
+
+	OPEN (UNIT=10,FILE='VMSMAIL_PROFILE',
+     &	     DEFAULTFILE='SYS$SYSTEM:VMSMAIL_PROFILE.DATA',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+
+	DO I=1,NUM_FOLDERS
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+
+	   IF (((.NOT.BTEST(USERB,31).AND.(USERB.NE.0.OR.GROUPB.NE.0)).OR.
+     &		 BTEST(GROUPB,31)).AND.FOLDER_BBOARD(:2).NE.'::'.AND.
+     &		 FOLDER_BBOARD(:4).NE.'NONE') THEN
+						! If normal BBOARD or /VMSMAIL
+	      DO WHILE (REC_LOCK(IER1))
+	         READ(10,'(A)',KEY=FOLDER_BBOARD,IOSTAT=IER1) INPUT
+	      END DO
+	      COUNT = 0
+	      IF (IER1.EQ.0) THEN
+		 INPUT = INPUT(32:)
+		 DO WHILE (TRIM(INPUT).GT.0)
+		    IF (ICHAR(INPUT(1:1)).EQ.1) THEN
+		       CALL LIB$MOVC3(2,%REF(INPUT(5:)),COUNT)
+		       INPUT = ' '
+		    ELSE
+		       INPUT = INPUT(ICHAR(INPUT(3:3))+5:)
+	            END IF
+	         END DO
+	      END IF
+	      IF (IER1.EQ.0.AND.(COUNT.GT.0.OR.IER.NE.0)) THEN
+		 NEW_MAIL(I) = .TRUE.
+	      ELSE
+		 NEW_MAIL(I) = .FALSE.
+	      END IF
+	   ELSE
+	      NEW_MAIL(I) = .TRUE.
+	   END IF
+	END DO
+
+	CLOSE (10)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETIMAGE(IMAGNAME,ILEN)
+C
+C  SUBROUTINE GETIMAGE(IMAGNAME,ILEN)
+C
+C  FUNCTION:
+C	To get image name of process.
+C  OUTPUT:
+C	IMAGNAME   -    Image name of process
+C	ILEN	   -	Length of imagename
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CHARACTER*(*) IMAGNAME
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST_WITH_RET(LEN(IMAGNAME),JPI$_IMAGNAME,
+     &					%LOC(IMAGNAME),%LOC(ILEN))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)	! Get Info command.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NEWEST_MSG(IN_BTIM,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	DIMENSION IN_BTIM(2)
+
+	IF (REMOTE_SET) THEN
+	   CALL REMOTE_GET_NEWEST_MSG(IN_BTIM,START)
+	ELSE
+	   CALL GET_MSGKEY(IN_BTIM,MSG_KEY)
+	   CALL READDIR_KEYGE(START)
+	   IF (START.EQ.0) THEN
+	      START = -1
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NOTIFY_REMOTE_USERS(IN_BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	DIMENSION IN_BTIM(2)
+
+	CALL OPEN_BULLDIR_SHARED
+	CALL GET_MSGKEY(IN_BTIM,MSG_KEY)
+	CALL READDIR_KEYGE(START)
+
+	IF (START.EQ.0) RETURN
+
+	CALL OPEN_BULLUSER_SHARED
+
+	IER = START + 1
+	DO WHILE (START+1.EQ.IER)
+	   IF (.NOT.BTEST(SYSTEM,3)) CALL NOTIFY_USERS(0)
+	   START = START + 1
+	   CALL READDIR(START,IER)
+	END DO
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+		! Reobtain present values as calling programs still uses them
+
+	CALL CLOSE_BULLUSER
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE READ_NOTIFY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*NOTIFY',IOSTAT=IER) TEMP_USER,NOTIFY_REMOTE
+	END DO
+
+	IF (IER.NE.0) THEN
+	   DO I=1,FLONG
+	      NOTIFY_REMOTE(I) = 0
+	   END DO
+	   WRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELPRC(DELNAM,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CHARACTER*(*) DELNAM
+
+	DATA OBIO/0/,OCPU/0/,ODIO/0/
+
+	CHARACTER PRCNAM*16
+
+	TEST = 'BULLCP NEWS'.EQ.DELNAM
+
+	WILDCARD = -1
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	
+	CALL ADD_2_ITMLST(LEN(PRCNAM),JPI$_PRCNAM,%LOC(PRCNAM))
+	CALL ADD_2_ITMLST(4,JPI$_PID,%LOC(PID))
+	IF (TEST) THEN 
+           CALL ADD_2_ITMLST(4,JPI$_BUFIO,%LOC(BIO))
+           CALL ADD_2_ITMLST(4,JPI$_CPUTIM,%LOC(CPU))
+           CALL ADD_2_ITMLST(4,JPI$_DIRIO,%LOC(DIO))
+	END IF
+ 	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+	IER = SYS$GETJPIW(,,DELNAM(:LEN(DELNAM)),%VAL(GETJPI_ITMLST),,,,)
+	IF (.NOT.IER) THEN 
+	   IER = 1
+	   DO WHILE (IER.AND.PRCNAM(:LEN(DELNAM)).NE.DELNAM)
+						! Get next interactive process
+	      IER = SYS$GETJPIW(,WILDCARD,,%VAL(GETJPI_ITMLST),,,,)
+						! Get next process.
+	   END DO
+	END IF
+	IF (IER.AND.PID.NE.0) THEN 
+	   IF (TEST.AND.
+     &		(BIO.GT.OBIO.OR.DIO.GT.ODIO.OR.CPU.GT.OCPU+10)) THEN
+	      OBIO = BIO
+	      ODIO = DIO
+	      OCPU = CPU
+	      IER = 0
+	      RETURN
+	   END IF
+	   IER = SYS$DELPRC(PID,)
+	   IF (IER.AND.TEST) THEN
+              OBIO = 0
+              ODIO = 0
+              OCPU = 0  
+	   END IF
+	END IF
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin4.for b/decus/vmslt00a/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..bde2891fa8bc892d34406e0a15c1241bbb645e39
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin4.for
@@ -0,0 +1,2349 @@
+C
+C  BULLETIN4.FOR, Version 12/17/97
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+C
+C  SUBROUTINE ITMLST_SUBS
+C
+C  FUNCTION:
+C	A set of routines to easily create item lists.  It allows one
+C  to easily create item lists without the need for declaring arrays
+C  or itemlist size.  Thus, the code can be easily changed to add or
+C  delete item list codes.
+C
+C  Here is an example of how to use the routines (prints file to a queue):
+C
+C	CALL INIT_ITMLST	! Initialize item list
+C				! Now add items to list
+C	CALL ADD_2_ITMLST(LEN,SJC$_FILE_SPECIFICATION,%LOC(FILENAME))
+C	CALL ADD_2_ITMLST(9,SJC$_QUEUE,%LOC(QUEUE))
+C	CALL END_ITMLST(SNDJBC_ITMLST)	! Get address of itemlist
+C	IER = SYS$SNDJBCW(,%VAL(SJC$_ENTER_FILE),,%VAL(SNDJBC_ITMLST),IOSB,,)
+C
+	SUBROUTINE ITMLST_SUBS
+
+	IMPLICIT INTEGER (A-Z)
+
+	DATA SAVE_ITMLST_ADDRESS/0/,NUM_ITEMS/0/,QUEUE_HEADER/0/
+
+	ENTRY INIT_ITMLST
+
+	IF (QUEUE_HEADER.EQ.0) THEN	! First time INIT_ITMLST ever called?
+	   CALL LIB$GET_VM(8,QUEUE_HEADER)  ! Yes, create queue header pointer
+	   CALL LIB$MOVC3(4,0,%VAL(QUEUE_HEADER))	! Zero out header
+	   CALL LIB$MOVC3(4,0,%VAL(QUEUE_HEADER+4))	! Zero out header
+	ELSE IF (SAVE_ITMLST_ADDRESS.GT.0) THEN	! Clean out old item list
+	   CALL LIB$FREE_VM((NUM_ITEMS+1)*12,SAVE_ITMLST_ADDRESS)
+	   NUM_ITEMS = 0		! Release old itemlist memory
+	   SAVE_ITMLST_ADDRESS = 0
+	ELSE				! ITMLST calls cannot be nested.
+	   WRITE (6,'('' ERROR: INIT_ITMLST called before previous'',$)')
+	   WRITE (6,'(''+ ITMLST terminated with END_ITMLST.'')')
+	   CALL EXIT
+	END IF
+
+	RETURN
+
+
+	ENTRY ADD_2_ITMLST(BUFLEN,CODE,BUFADR)
+C
+C  ITMLST entries are initially stored in a queue.  Each queue entry
+C  needs 8 bytes for pointer + 12 bytes for itemlist info.
+C
+	CALL LIB$GET_VM(20,INPUT_ITMLST)	! Get memory for entry
+
+	CALL STORE_ITMLST_ENTRY(%VAL(INPUT_ITMLST+8),BUFLEN,CODE,BUFADR,0)
+						! Store data in itemlist format
+	CALL LIB$INSQTI(%VAL(INPUT_ITMLST),%VAL(QUEUE_HEADER))
+						! Insert entry into queue
+	NUM_ITEMS = NUM_ITEMS + 1		! Increment item count
+
+	RETURN
+
+
+	ENTRY ADD_2_ITMLST_WITH_RET(BUFLEN,CODE,BUFADR,RETADR)
+C
+C  ITMLST entries are initially stored in a queue.  Each queue entry
+C  needs 8 bytes for pointer + 12 bytes for itemlist info.
+C
+	CALL LIB$GET_VM(20,INPUT_ITMLST)	! Get memory for entry
+
+	CALL STORE_ITMLST_ENTRY(%VAL(INPUT_ITMLST+8),BUFLEN,CODE,BUFADR,
+     &							RETADR)
+						! Store data in itemlist format
+	CALL LIB$INSQTI(%VAL(INPUT_ITMLST),%VAL(QUEUE_HEADER))
+						! Insert entry into queue
+	NUM_ITEMS = NUM_ITEMS + 1		! Increment item count
+
+	RETURN
+
+
+	ENTRY END_ITMLST(ITMLST_ADDRESS)
+
+	CALL LIB$GET_VM((NUM_ITEMS+1)*12,ITMLST_ADDRESS)
+						! Get memory for itemlist
+	SAVE_ITMLST_ADDRESS = ITMLST_ADDRESS	! Save address to remove memory
+
+	DO I=1,NUM_ITEMS			! Place entries into itemlist
+	   CALL LIB$REMQHI(%VAL(QUEUE_HEADER),INPUT_ITMLST)
+	   CALL LIB$MOVC3(12,%VAL(INPUT_ITMLST+8),
+     &		%VAL(ITMLST_ADDRESS+(I-1)*12))
+	   CALL LIB$FREE_VM(20,INPUT_ITMLST)
+	END DO
+
+	CALL LIB$MOVC3(4,0,%VAL(ITMLST_ADDRESS+NUM_ITEMS*12))
+					! Place terminating 0 at end of itemlist
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE STORE_ITMLST_ENTRY(INPUT_ITMLST,BUFLEN,CODE,BUFADR,
+     &							RETADR)
+
+	IMPLICIT INTEGER (A-Z)
+
+	STRUCTURE /ITMLST/
+	 UNION
+	  MAP
+	   INTEGER*2 BUFLEN,CODE
+	   INTEGER BUFADR,RETADR
+	  END MAP
+	 END UNION
+	END STRUCTURE
+
+	RECORD /ITMLST/ INPUT_ITMLST(1)
+
+	INPUT_ITMLST(1).BUFLEN = BUFLEN
+	INPUT_ITMLST(1).CODE = CODE
+	INPUT_ITMLST(1).BUFADR = BUFADR
+	INPUT_ITMLST(1).RETADR = RETADR
+
+	RETURN
+	END
+
+
+	SUBROUTINE CLEANUP_LOGIN
+C
+C  SUBROUTINE CLEANUP_LOGIN
+C
+C  FUNCTION: Removes entry in user file of user that no longer exist.
+C		It creates empty space for new user.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER*12 LOGIN_USER
+
+	CHARACTER TODAY*24
+
+	DIMENSION TODAY_BTIM(2)
+
+	MARK = SYS_TRNLNM_SYSTEM('BULL_MARK','DEFINED')
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	CALL OPEN_SYSUAF_SHARED
+
+	LOGIN_USER = USERNAME
+	READ (4,IOSTAT=IER1,KEYGT=USERNAME) USER_ENTRY	! Look forward one
+	TEMP_USER = USERNAME
+	USERNAME = LOGIN_USER
+	DO WHILE (REC_LOCK(IER))
+	   READ (8,KEY=TEMP_USER,IOSTAT=IER) TEMP_USER	! See if user exists
+	END DO
+
+	IF (IER.NE.0.AND.IER1.EQ.0.AND.TEMP_USER.NE.USER_HEADER_KEY) THEN
+				! If no UAF entry and last login was
+				! more than 6 months old, delete entry
+	   IF (MINUTE_DIFF(TODAY_BTIM,LOGIN_BTIM).GT.6*30*24*60) THEN
+	      DELETE(UNIT=4)			! Delete non-existant user
+	      CALL OPEN_BULLINF
+	      READ (9,KEY=TEMP_USER,IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE(UNIT=9)
+	      LU = TRIM(TEMP_USER)
+	      IF (MARK) CALL LIB$DELETE_FILE('BULL_MARK:'//
+     &					TEMP_USER(:LU)//'.*MARK;*')
+	      TEMP_USER(LU:LU) = CHAR(ICHAR(TEMP_USER(LU:LU)).OR.128)
+	      READ (9,KEY=TEMP_USER,IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE(UNIT=9)
+	      IF (LU.GT.1) THEN
+	         TEMP_USER(LU-1:LU-1) = 
+     &			CHAR(128.OR.ICHAR(TEMP_USER(LU-1:LU-1)))
+	      ELSE
+		 TEMP_USER(2:2) = CHAR(128.OR.ICHAR(TEMP_USER(2:2)))
+	      END IF
+	      READ (9,KEY=TEMP_USER,IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE(UNIT=9)
+	      CALL CLOSE_BULLINF
+	   END IF
+	END IF
+
+	CALL CLOSE_SYSUAF			! All done...
+
+	RETURN
+	END
+
+
+	SUBROUTINE TOTAL_CLEANUP_LOGIN
+C
+C  SUBROUTINE TOTAL_CLEANUP_LOGIN
+C
+C  FUNCTION: Removes all entries in user file of usesr that no longer exist
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	CHARACTER TODAY*24
+
+	DIMENSION TODAY_BTIM(2)
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	MARK = SYS_TRNLNM_SYSTEM('BULL_MARK','DEFINED')
+
+	CALL OPEN_SYSUAF_SHARED
+	CALL OPEN_BULLUSER
+	CALL OPEN_BULLINF
+
+	TEMP_USER = USERNAME
+
+	IER = 0
+
+	DO WHILE (IER.EQ.0)			! Clean out BULLUSER.DAT
+	   READ (4,IOSTAT=IER) USER_ENTRY
+	   IF (IER.EQ.0.AND.USERNAME(:1).NE.'*'.AND.
+     &	       USERNAME(:1).NE.':'.AND.
+     &	       USERNAME.NE.USER_HEADER_KEY) THEN	! See if user exists
+	      DO WHILE (REC_LOCK(IER))
+	         READ (8,KEY=USERNAME,IOSTAT=IER)
+	      END DO
+	      IF (IER.NE.0) THEN 	! If no UAF entry and last login was
+					! more than 6 months old, delete entry
+		 IF (MINUTE_DIFF(TODAY_BTIM,LOGIN_BTIM).GT.6*30*24*60) THEN
+	            DELETE (UNIT=4)
+		    READ (9,KEY=USERNAME,IOSTAT=IER)
+		    IF (IER.EQ.0) DELETE (UNIT=9)
+	            LU = TRIM(USERNAME)
+		    IF (MARK) CALL LIB$DELETE_FILE('BULL_MARK:'//
+     &					USERNAME(:LU)//'.*MARK;*')
+	            USERNAME(LU:LU) = CHAR(ICHAR(USERNAME(LU:LU)).OR.128)
+		    READ (9,KEY=USERNAME,IOSTAT=IER)
+		    IF (IER.EQ.0) DELETE (UNIT=9)
+		    IF (LU.GT.1) THEN
+		       USERNAME(LU-1:LU-1) = 
+     &			 CHAR(128.OR.ICHAR(USERNAME(LU-1:LU-1)))
+		    ELSE
+		       USERNAME(2:2) = CHAR(128.OR.ICHAR(USERNAME(2:2)))
+		    END IF
+		    READ (9,KEY=USERNAME,IOSTAT=IER)
+		    IF (IER.EQ.0) DELETE (UNIT=9)
+		 END IF
+		 IER = 0
+	      ELSE
+		 DO I=0,FOLDER_MAX-1
+		    IF (TEST2(NOTIFY_FLAG,I)) THEN
+		       CALL SET2(NOTIFY_REMOTE,I)
+		    END IF
+		 END DO
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_SYSUAF			! All done...
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*NOTIFY',IOSTAT=IER) TEMP_USER
+	END DO
+
+	IF (IER.NE.0) THEN
+	   WRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	ELSE
+	   REWRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	END IF
+
+	READ (9,KEYGT='            ',IOSTAT=IER) USERNAME
+
+	DO WHILE (IER.EQ.0)			! Clean out BULLINF.DAT
+	   LU = TRIM(USERNAME)
+	   USERNAME(LU:LU) = CHAR(ICHAR(USERNAME(LU:LU)).AND.127)
+	   IF (LU.GT.1) THEN
+	      USERNAME(LU-1:LU-1) = 
+     &			 CHAR(127.AND.ICHAR(USERNAME(LU-1:LU-1)))
+	   ELSE
+	      USERNAME(2:2) = CHAR(127.AND.ICHAR(USERNAME(2:2)))
+	   END IF
+	   READ (4,KEYEQ=USERNAME,IOSTAT=IER)
+	   IF (IER.NE.0) DELETE (UNIT=9)
+	   READ (9,IOSTAT=IER) USERNAME
+	END DO
+
+	CALL CLOSE_BULLINF
+	CALL CLOSE_BULLUSER
+
+	USERNAME = TEMP_USER
+
+	RETURN
+	END
+
+
+	SUBROUTINE COPY_BULL(INLUN,IBLOCK,OBLOCK,IER)
+C
+C  SUBROUTINE COPY_BULL
+C
+C  FUNCTION: To copy data to the bulletin file.
+C
+C  INPUT:
+C	INLUN	-	Input logical unit number
+C	IBLOCK	-	Input block number in input file to start at
+C	OBLOCK	-	Output block number in output file to start at
+C
+C  OUTPUT:
+C	IER	-	If error in writing to bulletin, IER will be <> 0.
+C
+C  NOTES:  Input file is accessed using sequential access.  This is 
+C	to allow files which have variable records to be read.  The
+C       bulletin file is assumed to be opened on logical unit 1.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	INCLUDE 'BULLDIR.INC'
+
+	IF (REMOTE_SET) THEN
+	   CALL REMOTE_COPY_BULL(IER)
+	   IF (IER.NE.0) CALL ERROR_AND_EXIT
+	END IF
+
+	DO I=1,IBLOCK-1
+	   READ(INLUN,'(A)')
+	END DO
+
+	OCOUNT = OBLOCK
+	ICOUNT = IBLOCK
+
+	NBLANK = 0
+	LENGTH = 0
+	DO WHILE (LENGTH.GE.0)
+	   ILEN = 0
+	   DO WHILE (ILEN.EQ.0)
+	      READ(INLUN,'(Q,A)',END=100) ILEN,INPUT
+	      ILEN = MIN(ILEN,TRIM(INPUT),LINE_LENGTH)
+	      IF (ILEN.GT.1.AND.ICHAR(INPUT(ILEN:ILEN)).EQ.10) THEN
+		 INPUT(ILEN-1:ILEN-1) = CHAR(32)	! Remove imbedded
+		 INPUT(ILEN:ILEN) = CHAR(32)	! CR/LFs at end of file.
+		 ILEN = ILEN - 2
+	      END IF
+	      IF (ILEN.GT.0) THEN
+		 IF (ICOUNT.EQ.IBLOCK) THEN
+		    IF (INPUT(:6).EQ.'From: ') THEN
+		       INPUT(:4) = 'FROM'
+		    END IF
+		 END IF
+		 ICOUNT = ICOUNT + 1
+	      ELSE IF (ILEN.EQ.0.AND.ICOUNT.GT.IBLOCK) THEN
+		 NBLANK = NBLANK + 1
+	      END IF
+	   END DO
+	   IF (NBLANK.GT.0) THEN
+	      DO I=1,NBLANK
+	         CALL STORE_BULL(1,' ',OCOUNT)
+	      END DO
+	      LENGTH = LENGTH + NBLANK*2
+	      NBLANK = 0
+	   END IF
+	   CALL STORE_BULL(ILEN,INPUT,OCOUNT)
+	   LENGTH = LENGTH + ILEN + 1
+	END DO
+
+100	LENGTH = (LENGTH+127)/128
+	IF (LENGTH.EQ.0) THEN
+	   IER = 1
+	ELSE
+	   IER = 0
+	END IF
+
+	CALL FLUSH_BULL(OCOUNT)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_BULL(ILEN,INPUT,OCOUNT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /STORE_POINT/ POINT
+	DATA POINT/-1/
+
+	CHARACTER INPUT*(*),OUTPUT*255
+
+	IF (POINT.EQ.-1) THEN
+	   POINT = 0
+	   IF (BTEST(FOLDER_FLAG,12)) CALL STORE_BULL1(0,CHAR(0),OCOUNT)
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,12)) THEN
+	   CALL COMPRESS(INPUT(:ILEN),OUTPUT,OLEN)
+	   CALL STORE_BULL1(OLEN,OUTPUT,OCOUNT)
+	ELSE
+	   CALL STORE_BULL1(ILEN,INPUT,OCOUNT)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_BULL1(ILEN,INPUT,OCOUNT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER BRECLEN=128
+
+	CHARACTER INPUT*(*),OUTPUT*256
+
+	COMMON /STORE_POINT/ POINT
+
+	IF (ILEN+POINT+1.GT.BRECLEN) THEN
+	   IF (POINT.EQ.BRECLEN) THEN
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:POINT))
+	      OUTPUT = CHAR(ILEN)//INPUT
+	      POINT = ILEN + 1
+	   ELSE IF (POINT.EQ.BRECLEN-1) THEN
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:POINT)//CHAR(ILEN))
+	      OUTPUT = INPUT
+	      POINT = ILEN
+	   ELSE
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:POINT)//CHAR(ILEN)
+     &		//INPUT(:BRECLEN-1-POINT))
+	      OUTPUT = INPUT(BRECLEN-POINT:)
+	      POINT = ILEN - (BRECLEN-1-POINT)
+	   END IF
+	   OCOUNT = OCOUNT + 1
+	   DO WHILE (POINT.GE.BRECLEN)
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:BRECLEN))
+	      OCOUNT = OCOUNT + 1
+	      OUTPUT = OUTPUT(BRECLEN+1:)
+	      POINT = POINT - BRECLEN
+	   END DO
+	ELSE
+	   OUTPUT(POINT+1:) = CHAR(ILEN)//INPUT(:ILEN)
+	   POINT = POINT + ILEN + 1
+	END IF
+
+	RETURN
+
+	ENTRY FLUSH_BULL(OCOUNT)
+
+	IF (POINT.LT.BRECLEN) OUTPUT(POINT+1:POINT+1) = CHAR(0)
+	CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:BRECLEN))
+	POINT = -1
+
+	RETURN
+
+	END
+
+
+	SUBROUTINE WRITE_BULL_FILE(OCOUNT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) OUTPUT
+
+	IF (REMOTE_SET) THEN
+	   CALL REMOTE_WRITE_BULL_FILE(OUTPUT)
+	ELSE
+	   WRITE (1'OCOUNT) OUTPUT
+	END IF
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_BULL_LINE(SBLOCK,BLENGTH,BUFFER,ILEN)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(*) BUFFER
+
+	COMMON /HEADER/ HEADER
+	LOGICAL HEADER /.TRUE./
+
+	COMMON /DATE/ DATE_LINE
+	CHARACTER*(INPUT_LENGTH) DATE_LINE
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+
+	IF (ILEN.GT.LINE_LENGTH) THEN		! First read?
+	   CALL STRIP_HEADER(' ',-1,IER)
+	   STRIP = .NOT.HEADER
+	   IBLOCK = SBLOCK			! Initialize pointers.
+	   BULL_HEADER = .TRUE.
+	   SEEN_FROM = .FALSE.
+	   SEEN_SUBJ = .FALSE.
+	   READ_HEAD = .FALSE.
+	   CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+	   IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+	   MSG_SENT = .FALSE.
+	   FINDREF = .NOT.STRIP.AND.REMOTE_SET.EQ.4
+	ELSE					! Else set ILEN to zero
+	   ILEN = 0				! to request next line
+	END IF
+
+	IF (MSG_SENT) THEN
+	   BUFFER = ' '
+	   ILEN = 1
+	   MSG_SENT = .FALSE.
+	   RETURN
+	END IF
+
+	DO WHILE (ILEN.GE.0)
+	   DO WHILE (ILEN.EQ.0)			! Read until line created
+	      CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+	      IF (ILEN.LE.0) IBLOCK = IBLOCK + 1    ! Need to read new record.
+	      IF (IBLOCK.GE.SBLOCK+BLENGTH) THEN    ! No more records.
+	         IF (STRIP.AND..NOT.READ_HEAD.AND.NHEAD.GT.0) THEN
+		     IBLOCK = SBLOCK
+		     ILEN = LINE_LENGTH+1
+		     CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+		     IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+		     READS = 0
+		     IF (SEEN_FROM) READS = READS + 1
+		     IF (SEEN_SUBJ) READS = READS + 1
+		     IF (MSG_SENT) READS = READS + 1
+		     IF (READS.GT.0) THEN
+		        DO I=1,READS
+		           ILEN = 0
+		           DO WHILE (ILEN.EQ.0)
+			      CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+			      IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+			   END DO
+		        END DO
+		     END IF
+		     STRIP = .FALSE.
+		 ELSE
+		     RETURN
+		 END IF
+	      END IF
+	   END DO
+
+	   IF (STRIP.OR.FINDREF) THEN
+	      IF (BULL_HEADER) THEN
+		 IF (BUFFER(:5).EQ.'From:'.AND..NOT.SEEN_FROM) THEN
+	            SEEN_FROM = .TRUE.
+		    RETURN
+		 ELSE IF (BUFFER(:5).EQ.'Subj:'.AND..NOT.SEEN_SUBJ) THEN
+	            SEEN_SUBJ = .TRUE.
+		    RETURN
+		 ELSE IF (BUFFER(:13).EQ.'Message sent:') THEN
+		    MSG_SENT = .TRUE.
+		    RETURN
+		 ELSE
+		    BULL_HEADER = .FALSE.
+		    IF (REMOTE_SET.EQ.4) FOUNDREF = .FALSE. 
+		 END IF
+	      END IF
+              IF (REMOTE_SET.EQ.4.AND.ILEN.GT.12.AND.
+     &			(BUFFER(1:11).EQ.'References:'.OR.
+     &			 BUFFER(1:11).EQ.'Message-ID:')) THEN
+	         IF (.NOT.FOUNDREF) LREF = 0
+	         FOUNDREF = .TRUE.
+		 IF (LREF.EQ.0) THEN
+		    REFERENCES = BUFFER(13:ILEN)
+		 ELSE
+		    REFERENCES = REFERENCES(:LREF)//' '//
+     &				BUFFER(13:ILEN)
+		 END IF
+		 LREF = TRIM(REFERENCES)
+	      END IF
+	      IF (STRIP) THEN
+	         IF (DATE_LINE.NE.' ') DATE_LINE = ' '
+	         CALL STRIP_HEADER(BUFFER,ILEN,STRIP)
+	         IF (DATE_LINE.NE.' '.AND..NOT.MAIL_POST()) THEN
+		    BUFFER = DATE_LINE
+		    ILEN = TRIM(DATE_LINE)
+		    MSG_SENT = .TRUE.
+		    RETURN
+	         END IF
+	         IF (STRIP.OR.(.NOT.STRIP.AND.TRIM(BUFFER).EQ.0)) ILEN = 0
+		 IF (STRIP.AND.BUFFER(:5).EQ.'From:') READ_HEAD = .TRUE.
+	         IF (.NOT.STRIP.AND..NOT.READ_HEAD.AND.NHEAD.GT.0) THEN
+		     IBLOCK = SBLOCK
+		     ILEN = LINE_LENGTH+1
+		     CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+		     IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+		     READS = 0
+		     IF (SEEN_FROM) READS = READS + 1
+		     IF (SEEN_SUBJ) READS = READS + 1
+		     IF (MSG_SENT) READS = READS + 1
+		     IF (READS.GT.0) THEN
+		        DO I=1,READS
+		           ILEN = 0
+		           DO WHILE (ILEN.EQ.0)
+			      CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+			      IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+			   END DO
+		        END DO
+		     END IF
+		 END IF
+	      ELSE
+	         IF (.NOT.HEADER) THEN
+		    CALL STRIP_HEADER(BUFFER,ILEN,STRIP)
+		    STRIP = .FALSE.
+	         END IF
+	         IF (TRIM(BUFFER).EQ.0) THEN
+		    FINDREF = .FALSE.
+	            IF (.NOT.FOUNDREF) LREF = 0 
+	         END IF
+	         RETURN
+	      END IF
+	   ELSE
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+
+	ENTRY TEST_MORE_RECORDS(SBLOCK,BLENGTH,IREC)
+
+	IREC = (SBLOCK+BLENGTH-1) - IBLOCK
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_BULL(IBLOCK,BUFFER,OLEN)
+C
+C  SUBROUTINE GET_BULL
+C
+C  FUNCTION:  Outputs line from folder file.
+C
+C  INPUT:
+C	IBLOCK	-	Input block number in input file to read from.
+C
+C  OUTPUT:
+C	BUFFER  -	Character string containing output line.
+C	OLEN	-	Length of character string.  If 0, signifies that
+C			new record needs to be read, -1 signifies error.
+C
+C  NOTE:  Since message file is stored as a fixed length (128) record file,
+C	  but message lines are variable, message lines may span one or
+C	  more record.  This routine takes a record and outputs as many
+C	  lines as it can from the record.  When no more lines can be
+C	  outputted, it returns OLEN=0 requesting the calling program to
+C	  increment the record counter.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REMOTE_READ_MESSAGE/ SCRATCH_R1
+	DATA SCRATCH_R1 /0/
+
+	PARAMETER BRECLEN=128
+
+	CHARACTER BUFFER*(*),TEMP*(BRECLEN), LEFT*(INPUT_LENGTH)
+
+	DATA POINT /1/, LEFT_LEN /0/
+
+	IF (OLEN.GT.LINE_LENGTH) THEN		! First read?
+	   POINT = 1				! Initialize pointers.
+	   LEFT_LEN = 0
+	   DTYPE = 0
+	END IF
+
+	IF (POINT.EQ.1) THEN			! Need to read new line?
+10	   IF (INCMD(:4).EQ.'MOVE'.OR.INCMD(:4).EQ.'COPY') THEN
+	      DO WHILE (REC_LOCK(IER))		! Read from file
+	         READ (11'IBLOCK,IOSTAT=IER) TEMP
+	      END DO
+	   ELSE IF (REMOTE_SET) THEN		! Remote folder?
+	      IF (IBLOCK.EQ.BLOCK) SCRATCH_R = SCRATCH_R1	! Read lines
+	      CALL READ_QUEUE(%VAL(SCRATCH_R),SCRATCH_R,TEMP)	! from queue
+	      IER = 0
+	   ELSE					! Local folder
+	      DO WHILE (REC_LOCK(IER))		! Read from file
+	         READ (1'IBLOCK,IOSTAT=IER) TEMP
+	      END DO
+	   END IF
+	   IF (OLEN.GT.LINE_LENGTH.AND.IER.EQ.0
+     &		.AND.ICHAR(TEMP(:1)).EQ.0) THEN
+	      DTYPE = 1
+	      POINT = POINT + 1
+           END IF
+	ELSE IF (POINT.EQ.BRECLEN+1) THEN	! Read all of line
+	   OLEN = 0				! so indicate need to read
+	   POINT = 1				! new line to calling routine.
+	   RETURN
+	END IF
+
+	IF (IER.GT.0) THEN			! Error in reading file.
+	   OLEN = -1				! OLEN = -1 signifies error
+	   POINT = 1
+	   LEFT_LEN = 0
+	   RETURN
+	END IF
+
+	IF (LEFT_LEN.GT.0) THEN			! Part of line is left from
+	   OLEN = ICHAR(LEFT(:1))		! previous record read.
+	   IF (LEFT_LEN.LE.BRECLEN) THEN	! Rest of it is in next record.
+ 	      IF (DTYPE.EQ.0) THEN
+	         BUFFER = LEFT(2:OLEN-LEFT_LEN+1)//
+     &					TEMP(:LEFT_LEN) ! Output line.
+	      ELSE
+	         CALL UNCOMPRESS(LEFT(2:OLEN-LEFT_LEN+1)
+     &				 //TEMP(:LEFT_LEN),BUFFER,OLEN)
+ 	      END IF
+	      POINT = LEFT_LEN + 1		! Update pointers.
+	      LEFT_LEN = 0
+	   ELSE					! Rest of line is longer than
+	      LEFT(OLEN-LEFT_LEN+2:) = TEMP	! a record, so store record
+	      LEFT_LEN = LEFT_LEN - BRECLEN	! and request another read.
+	      OLEN = 0				! Request new record read.
+	   END IF
+	ELSE					! Else nothing left over.
+	   OLEN = ICHAR(TEMP(POINT:POINT))	! Get line length
+	   IF (OLEN.GT.BRECLEN-POINT) THEN	! If it extends to next record
+	      LEFT = TEMP(POINT:)		! Store it in leftover buffer
+	      LEFT_LEN = OLEN - (BRECLEN-POINT)	! Store leftover length
+	      OLEN = 0				! Request new record read
+	      POINT = 1				! Update record pointer.
+	   ELSE IF (OLEN.EQ.0) THEN		! Empty line signifies
+	      POINT = 1				! end of message.
+	   ELSE					! Else message line fully read
+	      ILEN = OLEN
+	      IF (DTYPE.EQ.0) THEN
+	         BUFFER = TEMP(POINT+1:POINT+ILEN)	! So output it
+	         OLEN = OLEN
+	      ELSE
+	         CALL UNCOMPRESS(TEMP(POINT+1:POINT+ILEN),BUFFER,OLEN)
+	      END IF
+	      POINT = POINT+ILEN+1		! and update pointer.
+	   END IF
+	END IF
+
+	RETURN
+
+	ENTRY TEST_MORE_LINES(OLEN)	! Test for more lines in record.
+					! Returns length of next line.
+	IF (POINT.EQ.BRECLEN+1) THEN		! If pointer greater than
+	   OLEN = 0				! record, no more lines.
+	ELSE					! Else there is another line.
+	   OLEN = ICHAR(TEMP(POINT:POINT))	! Output it's length.
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE DELETE_ENTRY(BULL_ENTRY)
+C
+C  SUBROUTINE DELETE_ENTRY
+C
+C  FUNCTION:
+C	To delete a directory entry.
+C
+C  INPUTS:
+C	BULL_ENTRY  -  Bulletin entry number to delete
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	IF (NBULL.GT.0) THEN
+	   CALL READDIR(0,IER)
+	   NBULL = -NBULL
+	   CALL WRITEDIR(0,IER)
+	END IF
+
+	CALL DUMP_MESSAGE()
+
+	CALL READDIR(BULL_ENTRY,IER)
+	DELETE(UNIT=2)
+
+	NEMPTY = NEMPTY + LENGTH
+
+	CALL WRITEDIR(0,IER)
+
+	RETURN
+	END
+
+
+	SUBROUTINE DUMP_MESSAGE()
+C
+C  SUBROUTINE DUMP_MESSAGE
+C
+C  FUNCTION:
+C	To delete a directory entry.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($ACLDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /ACL/ ACLENT
+	CHARACTER ACLENT*256
+
+	CHARACTER DUMP_FILE*80
+
+	IF (BTEST(FOLDER_FLAG,1)) THEN
+	   DUMP_FILE = FOLDER_FILE
+           IF (REMOTE_SET.EQ.4) THEN
+	      DUMP_FILE = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	      DO I=1,TRIM(DUMP_FILE)
+                 IF (DUMP_FILE(I:I).EQ.'.') DUMP_FILE(I:I) = '_'
+	      END DO	
+	      DUMP_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//
+     &				DUMP_FILE
+	   END IF
+	   OPEN(UNIT=3,FILE=DUMP_FILE(:TRIM(DUMP_FILE))//'.LOG',
+     &		IOSTAT=IER,STATUS='OLD',
+     &		RECL=LINE_LENGTH,CARRIAGECONTROL='LIST',ACCESS='APPEND')
+	   IF (IER.NE.0) THEN
+	      OPEN(UNIT=3,FILE=DUMP_FILE(:TRIM(DUMP_FILE))//'.LOG',
+     &		IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      IF (IER.NE.0) RETURN
+
+	      IER = SYS$PARSE_ACL('(IDENTIFIER='//FOLDER_OWNER(
+     &		:TRIM(FOLDER_OWNER))//',ACCESS=R+W+E+D+C)',ACLENT,,)
+       	      IF (IER) THEN
+		 CALL INIT_ITMLST	! Initialize item list
+		 CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_ADDACLENT,
+     &			%LOC(ACLENT))
+		 CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+		 IER = SYS$CHANGE_ACL(,ACL$C_FILE,DUMP_FILE(:TRIM(
+     &		   DUMP_FILE))//'.LOG',%VAL(ACL_ITMLST),,,)
+              END IF
+	   ELSE
+	      WRITE (3,'(A)') CHAR(12)
+	   END IF
+
+	   CALL OPEN_BULLFIL
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      WRITE(3,1060) INPUT(7:ILEN),DATE//' '//TIME(:8)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE
+	      WRITE(3,1060) FROM,DATE//' '//TIME(:8)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      WRITE(3,1050) INPUT(7:MIN(ILEN,LINE_LENGTH-3))
+	   ELSE
+	      WRITE(3,1050) DESCRIP
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END DO
+
+	   CLOSE (UNIT=3)			! Bulletin copy completed
+
+	   CALL CLOSE_BULLFIL
+	END IF
+
+1050	FORMAT('Subject: ',A,/)
+1060	FORMAT(/,'From: ',A,' Date: ',A11)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_EXDATE(EXDATE,NDAYS)
+C
+C  SUBROUTINE GET_EXDATE
+C
+C  FUNCTION:  Computes expiration date giving number of days to expire.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*12 EXDATE
+
+	CHARACTER*3 MONTHS(12)
+	DIMENSION LENGTH(12)
+	DATA MONTHS/'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP',
+     &		    'OCT','NOV','DEC'/
+	DATA LENGTH/31,27,31,30,31,30,31,31,30,31,30,31/
+
+	CALL SYS$ASCTIM(,EXDATE,,)		! Get the present date
+
+	DECODE(2,'(I2)',EXDATE(:2)) DAY	! Get day
+	DECODE(4,'(I4)',EXDATE(8:11)) YEAR	! Get year
+
+	MONTH = 1
+	DO WHILE (MONTHS(MONTH).NE.EXDATE(4:6))	! Get month
+	   MONTH = MONTH + 1
+	END DO
+
+	IF (MOD(YEAR,4).EQ.0) THEN		! Correct February length
+	   LENGTH(2) = 28			! if we're in a leap year
+	ELSE
+	   LENGTH(2) = 27
+	END IF
+
+	NUM_DAYS = NDAYS	! Put number of days into buffer variable
+
+	DO WHILE (NUM_DAYS.GT.0)
+	   IF (NUM_DAYS+DAY.GT.LENGTH(MONTH)) THEN
+				! If expiration date exceeds end of month
+	      NUM_DAYS = NUM_DAYS - (LENGTH(MONTH) - DAY + 1)
+				! Decrement # of days by days left in month
+	      DAY = 1				! Reset day to first of month
+	      MONTH = MONTH + 1			! Increment month pointer
+	      IF (MONTH.EQ.13) THEN		! Moved into next year?
+		 MONTH = 1			! Reset month pointer
+		 YEAR = YEAR + 1		! Increment year pointer
+	         IF (MOD(YEAR,4).EQ.0) THEN	! Correct February length
+	            LENGTH(2) = 28		! if we're in a leap year
+	         ELSE
+	            LENGTH(2) = 27
+	         END IF
+	      END IF
+	   ELSE			! If expiration date is within the month
+	      DAY = DAY + NUM_DAYS		! Find expiration day
+	      NUM_DAYS = 0			! Force loop exit
+	   END IF
+	END DO
+
+	CALL OTS$CVT_L_TI (DAY,EXDATE(:2),%VAL(2))
+	CALL OTS$CVT_L_TI (YEAR,EXDATE(8:11),%VAL(4))
+
+C	ENCODE(2,'(I2)',EXDATE(:2)) DAY	! Put day into new date
+C  	ENCODE(4,'(I4)',EXDATE(8:11)) YEAR	! Put year into new date
+	EXDATE(4:6) = MONTHS(MONTH)		! Put month into new date
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_LINE(INPUT,LEN_INPUT)
+C
+C  SUBROUTINE GET_LINE
+C
+C  FUNCTION:
+C	Gets line of input from terminal.
+C
+C  OUTPUTS:
+C	LEN_INPUT  -  Length of input line.  If = -1, CTRLC entered.
+C		      if = -2, CTRLZ entered.
+C
+C  NOTES:
+C	Also, on first call, set LEN_INPUT to 1+LENGTH OF INPUT CHARCTER
+C	for initializing the CTRLC AST.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	LOGICAL*1 DESCRIP(8),DTYPE,CLASS
+	INTEGER*2 LENGTH
+	CHARACTER*(*) INPUT
+	EQUIVALENCE (DESCRIP(1),LENGTH),(DESCRIP(3),DTYPE)
+	EQUIVALENCE (DESCRIP(4),CLASS),(DESCRIP(5),POINTER)
+
+        DATA LENGTH/0/,DTYPE/0/,CLASS/2/,POINTER/0/
+
+	EXTERNAL SMG$_EOF
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	CHARACTER PROMPT*(*),NULLPROMPT*4
+	LOGICAL USE_PROMPT
+
+	USE_PROMPT = .FALSE.
+
+	GO TO 5
+
+	ENTRY GET_INPUT_PROMPT(INPUT,LEN_INPUT,PROMPT)
+
+	USE_PROMPT = .TRUE.
+
+5	LIMIT = LEN(INPUT)			! Get input line size limit
+	INPUT = ' '				! Clean out input buffer
+
+C
+C  Initialize CTRL-C AST with AST routine CTRLC_ROUTINE and
+C  AST parameter FLAG.  When CTRLC occurs, FLAG is set to 1
+C
+
+	CALL DECLARE_CTRLC_AST
+
+	LEN_INPUT = 0				! Nothing inputted yet
+
+C
+C  LIB$GET_INPUT is nice way of getting input from terminal,
+C  as it handles such thing as accidental wrap around to next line.
+C
+
+	IF (DECNET_PROC) THEN
+	   READ (5,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   IF (IER.NE.0) LEN_INPUT = -2 
+	   RETURN
+	ELSE IF (USE_PROMPT) THEN
+	   IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		DESCRIP,PROMPT)		! Get line from terminal with prompt
+	ELSE
+	   IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		DESCRIP,NULLPROMPT(:1))	! Get line from terminal with no prompt
+	END IF
+
+	IF (.NOT.IER.AND.IER.NE.%LOC(SMG$_EOF)) CALL EXIT(IER)
+
+	CALL STR$TRIM(DESCRIP,DESCRIP,LEN_INPUT)
+
+	IF (FLAG.EQ.0) THEN			! If no CTRL-C has occurred
+	   CALL CANCEL_CTRLC_AST		! Cancel CTRL-C AST
+	   IF (IER.NE.%LOC(SMG$_EOF)) THEN	! End of input?
+	      LEN_INPUT = MIN(LIMIT,LENGTH)	! No. Get length of line
+	      DO I=0,LEN_INPUT-1		! Extract from descriptor
+	         CALL GET_VAL(INPUT(I+1:I+1),%VAL(POINTER+I))
+	      END DO
+	      CALL CONVERT_TABS(INPUT,LEN_INPUT)
+	      LEN_INPUT = MAX(LEN_INPUT,LENGTH)
+	   ELSE
+	      LEN_INPUT = -2			! If CTRL-Z, say so
+	   END IF
+	ELSE
+	   LEN_INPUT = -1			! If CTRL-C, say so
+	END IF
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_TABS(INPUT,LEN_INPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT
+
+	PARAMETER TAB = CHAR(9)
+
+	LIMIT = LEN(INPUT)
+
+	DO WHILE (INDEX(INPUT,TAB).GT.0.AND.LEN_INPUT.LT.LIMIT)
+	   TAB_POINT = INDEX(INPUT,TAB)	! Remove tabs
+	   MOVE = ((TAB_POINT-1)/8)*8 + 9
+	   ADD = MOVE - TAB_POINT
+	   IF (MOVE-1.LE.LIMIT) THEN
+	      INPUT(MOVE:) = INPUT(TAB_POINT+1:)
+	      DO I = TAB_POINT,MOVE-1
+	         INPUT(I:I) = ' '
+	      END DO
+	      LEN_INPUT = LEN_INPUT + ADD - 1
+	   ELSE
+	      DO I = TAB_POINT,LIMIT
+	         INPUT(I:I) = ' '
+	      END DO
+	      LEN_INPUT = LIMIT+1
+	   END IF
+	END DO
+
+        CALL FILTER (INPUT, LEN_INPUT)
+
+	RETURN
+	END
+
+
+	SUBROUTINE FILTER (INCHAR, LENGTH)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INCHAR
+
+	DO I = 1,LENGTH
+	   IF ((INCHAR(I:I).LT.' '.AND.
+     &      INCHAR(I:I).NE.CHAR(13).AND.INCHAR(I:I).NE.CHAR(10)))
+     &	    INCHAR(I:I) = '.'
+	END DO
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_VAL(OUTPUT,INPUT)	! Used to convert logical
+	CHARACTER*(*) OUTPUT			! byte to character value
+	LOGICAL*1 INPUT
+	OUTPUT = CHAR(INPUT)
+	RETURN
+	END
+
+	SUBROUTINE CTRLC_ROUTINE		! CTRL-C AST routine
+	IMPLICIT INTEGER (A-Z)			! If CTRL-C, come here
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /DEF_PROT/ ORIGINAL_DEF_PROT
+
+	IF (FLAG.EQ.2) THEN
+	   CALL LIB$PUT_OUTPUT('Bulletin aborting...')
+	   CALL SYS$CANEXH()
+	   CALL SYS$SETDFPROT(ORIGINAL_DEF_PROT,)
+	   CALL LIB$ENABLE_CTRL(CTRLY,)		! Enable CTRL-Y & -C
+	   CALL EXIT
+	END IF
+	FLAG = 1				! to set flag
+	RETURN
+	END
+
+
+
+	SUBROUTINE DECLARE_CTRLC_AST
+C
+C  SUBROUTINE DECLARE_CTRLC_AST
+C
+C  FUNCTION:
+C	Declares a CTRLC ast.
+C  NOTES:
+C	Assumes terminal assigned to TERM_CHAN in common /TERM_CHAN/.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	EXTERNAL IO$_SETMODE,IO$M_CTRLCAST,CTRLC_ROUTINE
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	FLAG = 0				! Init CTRL-C flag
+	IO_CTRLC = %LOC(IO$_SETMODE)+%LOC(IO$M_CTRLCAST)	! Set AST code
+	IER=SYS$QIOW(,%VAL(TERM_CHAN),%VAL(IO_CTRLC),,,,	! for QIO
+     &	      CTRLC_ROUTINE,,,,,)		! Enable the AST
+
+	RETURN
+
+	ENTRY CANCEL_CTRLC_AST
+
+	IER = SYS$CANCEL(%VAL(TERM_CHAN))
+
+	FLAG = 2		! Indicates that a CTRLC will cause an exit
+	IER=SYS$QIOW(,%VAL(TERM_CHAN),%VAL(IO_CTRLC),,,,	! for QIO
+     &	      CTRLC_ROUTINE,,,,,)		! Enable the AST
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_INPUT_NOECHO(DATA)
+C
+C  SUBROUTINE GET_INPUT_NOECHO
+C
+C  FUNCTION: Reads data in from terminal without echoing characters.
+C	     Also contains entry to assign terminal.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) DATA,PROMPT
+
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /READIT/ READIT
+
+	INCLUDE '($TRMDEF)'
+
+	INTEGER TERMSET(2)
+
+	INTEGER MASK(4)
+	DATA MASK/4*'FFFFFFFF'X/
+
+	DATA PURGE/.TRUE./
+
+	DO I=1,LEN(DATA)
+	   DATA(I:I) = ' '
+	END DO
+
+	IF (PURGE) THEN
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),
+     &		TRM$M_TM_NOECHO.OR.TRM$M_TM_PURGE)
+	   PURGE = .FALSE.
+	ELSE
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),
+     &		TRM$M_TM_NOECHO)
+	END IF
+
+	RETURN
+
+	ENTRY GET_INPUT_NOECHO_PROMPT(DATA,PROMPT)
+
+	DO I=1,LEN(DATA)
+	   DATA(I:I) = ' '
+	END DO
+
+	IF (PURGE) THEN
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,PROMPT,LEN(DATA),
+     &		TRM$M_TM_NOECHO.OR.TRM$M_TM_PURGE)
+	   PURGE = .FALSE.
+	ELSE
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,PROMPT,LEN(DATA),
+     &		TRM$M_TM_NOECHO)
+	END IF
+
+	RETURN
+
+	ENTRY GET_INPUT_NUM(DATA,NLEN)
+
+	DO I=1,LEN(DATA)
+	   DATA(I:I) = ' '
+	END DO
+
+	IF (PURGE) THEN
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),
+     &		TRM$M_TM_PURGE,,TERMSET,NLEN,TERM)
+	   PURGE = .FALSE.
+	ELSE
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),,,
+     &		TERMSET,NLEN,TERM)
+	END IF
+
+	IF (TERM.NE.13.AND.TERM.NE.510.AND.NLEN.EQ.0) THEN
+				! Input did not end with CR or buffer full
+	   NLEN = 1
+	   DATA(:1) = CHAR(TERM)
+	END IF
+
+	RETURN
+
+	ENTRY ASSIGN_TERMINAL
+
+	IER = SYS$ASSIGN('TT',TERM_CHAN,,)	! Assign terminal
+
+	CALL DECLARE_CTRLC_AST
+
+	FLAG = 2		! Indicates that a CTRLC will cause an exit
+
+	IER = SMG$CREATE_VIRTUAL_KEYBOARD(KEYBOARD_ID,,,,20)
+
+	IER = SMG$CREATE_KEY_TABLE(KEY_TABLE_ID)
+
+	IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,0)
+
+	IF (CLI$PRESENT('KEYPAD')) THEN
+	   CALL SET_KEYPAD
+	ELSE IF (READIT.EQ.0) THEN
+	   CALL SET_NOKEYPAD
+	END IF
+
+	TERMSET(1) = 16
+	TERMSET(2) = %LOC(MASK)
+
+	DO I=ICHAR('0'),ICHAR('9')
+	   MASK(2) = IBCLR(MASK(2),I-32)
+	END DO
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GETPAGSIZ(PAGE_LENGTH,PAGE_WIDTH)
+C
+C  SUBROUTINE GETPAGSIZ
+C
+C  FUNCTION:
+C	Gets page size of the terminal.
+C
+C  OUTPUTS:
+C	PAGE_LENGTH  -  Page length of the terminal.
+C	PAGE_WIDTH   -  Page size of the terminal.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($DVIDEF)'
+
+	LOGICAL*1 DEVDEPEND(4)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,DVI$_DEVDEPEND,%LOC(DEVDEPEND(1)))
+	CALL ADD_2_ITMLST(4,DVI$_DEVBUFSIZ,%LOC(PAGE_WIDTH))
+	CALL END_ITMLST(GETDVI_ITMLST)		! Get address of itemlist
+
+	CALL SYS$GETDVIW(,,'TT',%VAL(GETDVI_ITMLST),,,,)
+
+	PAGE_LENGTH = ZEXT(DEVDEPEND(4))
+
+	PAGE_WIDTH = MIN(PAGE_WIDTH,132)
+
+	RETURN
+	END
+
+
+
+
+
+	LOGICAL FUNCTION SLOW_TERMINAL
+C
+C  FUNCTION SLOW_TERMINAL
+C
+C  FUNCTION:
+C	Indicates that terminal has a slow speed (2400 baud or less).
+C
+C  OUTPUTS:
+C	SLOW_TERMINAL = .true. if slow, .false. if not.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	EXTERNAL IO$_SENSEMODE
+
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	COMMON CHAR_BUF(2)
+
+	LOGICAL*1 IOSB(8)
+
+	INCLUDE '($TTDEF)'
+
+	IER = SYS$QIOW(,%VAL(TERM_CHAN),IO$_SENSEMODE,IOSB,,,
+     &		  CHAR_BUF,%VAL(8),,,,)
+
+	IF (IOSB(3).LE.TT$C_BAUD_2400.AND.IOSB(3).NE.0) THEN
+	   SLOW_TERMINAL = .TRUE.
+	ELSE
+	   SLOW_TERMINAL = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOW_PRIV
+C
+C  SUBROUTINE SHOW_PRIV
+C
+C  FUNCTION:
+C	To show privileges necessary for managing bulletin board.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /PRVDEF/ PRIVS
+	CHARACTER*8 PRIVS(0:38)
+
+	CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+
+	CALL READ_USER_FILE_HEADER(IER)
+
+	IF (IER.EQ.0) THEN			! If header is present, exit
+	   IF (NEW_FLAG(1).EQ.-1.AND.NEW_FLAG(2).EQ.-1) THEN  ! Info not present
+	      CALL CLOSE_BULLUSER
+	      CALL OPEN_BULLUSER			! Get BULLUSER.DAT file
+	      CALL READ_USER_FILE_HEADER(IER)
+	      USERPRIV(1) = PRV$M_OPER.OR.PRV$M_CMKRNL.OR.PRV$M_SETPRV
+	      USERPRIV(2) = 0
+	      REWRITE (4) USER_HEADER
+	   END IF
+	   WRITE (6,'('' Following privileges are needed for privileged
+     & commands:'')')
+	   DO I=0,38
+	      IF ((I.LT.32.AND.BTEST(USERPRIV(1),I)).OR.
+     &		  (I.GT.31.AND.BTEST(USERPRIV(2),I-32))) THEN
+		 WRITE (6,'(1X,A)') PRIVS(I)
+	      END IF
+	   END DO
+	ELSE
+	   WRITE (6,'('' ERROR: Cannot show privileges.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER			! All finished with BULLUSER
+
+	CALL CHKACL(BULLUSER_FILE(:TRIM(BULLUSER_FILE)),IER)
+	IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.IER) THEN
+	   CALL SHOWACL(BULLUSER_FILE(:TRIM(BULLUSER_FILE)))
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE SET_PRIV
+C
+C  SUBROUTINE SET_PRIV
+C
+C  FUNCTION:
+C	To set privileges necessary for managing bulletin board.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	COMMON /PRVDEF/ PRIVS
+	CHARACTER*8 PRIVS(0:38)
+	DATA PRIVS
+     &	/'CMKRNL','CMEXEC','SYSNAM','GRPNAM','ALLSPOOL','DETACH',
+     &  'DIAGNOSE','LOG_IO','GROUP','ACNT','PRMCEB','PRMMBX','PSWAPM',
+     &	'ALTPRI','SETPRV','TMPMBX','WORLD','MOUNT','OPER','EXQUOTA',
+     &	'NETMBX','VOLPRO','PHY_IO','BUGCHK','PRMGBL','SYSGBL','PFNMAP',
+     &	'SHMEM','SYSPRV','BYPASS','SYSLCK','SHARE','UPGRADE','DOWNGRADE',
+     &	'GRPPRV','READALL',' ',' ','SECURITY'/
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	DIMENSION ONPRIV(2),OFFPRIV(2)
+
+	CHARACTER*32 INPUT_PRIV
+
+	IF (.NOT.SETPRV_PRIV().OR..NOT.BTEST(PROCPRIV(1),PRV$V_SETPRV)) THEN
+	   WRITE (6,'('' ERROR: This command requires SETPRV privileges.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('ID').OR.
+     &		CLI$PRESENT('ID').EQ.%LOC(CLI$_NEGATED)) THEN
+	   DO WHILE (CLI$GET_VALUE('PRIVILEGES',INPUT_PRIV,PLEN)
+     &	       .NE.%LOC(CLI$_ABSENT))		! Get the IDs
+	      IF (CLI$PRESENT('ID')) THEN
+		 CALL ADD_ACL(INPUT_PRIV(:PLEN),'R+C',IER)
+	      ELSE
+		 CALL DEL_ACL(INPUT_PRIV(:PLEN),'R+C',IER)
+	      END IF
+	      IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   END DO
+	   RETURN
+	END IF
+
+	OFFPRIV(1) = 0
+	OFFPRIV(2) = 0
+	ONPRIV(1) = 0
+	ONPRIV(2) = 0
+
+	DO WHILE (CLI$GET_VALUE('PRIVILEGES',INPUT_PRIV,PLEN)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the privileges
+	   PRIV_FOUND = -1
+	   I = 0
+	   DO WHILE (I.LT.39.AND.PRIV_FOUND.EQ.-1)
+	      IF (INPUT_PRIV(:PLEN).EQ.PRIVS(I)) PRIV_FOUND = I
+	      IF (INPUT_PRIV(3:PLEN).EQ.PRIVS(I)) PRIV_FOUND = I
+	      I = I + 1
+	   END DO
+	   IF (PRIV_FOUND.EQ.-1) THEN
+	      WRITE(6,'('' ERROR: Incorrectly specified privilege = '',
+     &		A)') INPUT_PRIV(:PLEN)
+	      RETURN
+	   ELSE IF (INPUT_PRIV(:2).EQ.'NO') THEN
+	      IF (INPUT_PRIV.EQ.'NOSETPRV') THEN
+	       WRITE(6,'('' ERROR: Cannot remove SETPRV privileges.'')')
+	       RETURN
+	      ELSE IF (PRIV_FOUND.LT.32) THEN
+		 OFFPRIV(1) = IBSET(OFFPRIV(1),PRIV_FOUND)
+	      ELSE
+		 OFFPRIV(2) = IBSET(OFFPRIV(2),PRIV_FOUND-32)
+	      END IF
+	   ELSE
+	      IF (PRIV_FOUND.LT.32) THEN
+		 ONPRIV(1) = IBSET(ONPRIV(1),PRIV_FOUND)
+	      ELSE
+		 ONPRIV(2) = IBSET(ONPRIV(2),PRIV_FOUND-32)
+	      END IF
+	   END IF
+	END DO
+
+	CALL OPEN_BULLUSER		! Get BULLUSER.DAT file
+
+	CALL READ_USER_FILE_HEADER(IER)
+
+	IF (IER.EQ.0) THEN			! If header is present, exit
+	   USERPRIV(1) = USERPRIV(1).OR.ONPRIV(1)
+	   USERPRIV(2) = USERPRIV(2).OR.ONPRIV(2)
+	   USERPRIV(1) = USERPRIV(1).AND.(.NOT.OFFPRIV(1))
+	   USERPRIV(2) = USERPRIV(2).AND.(.NOT.OFFPRIV(2))
+	   REWRITE (4) USER_HEADER
+	   WRITE (6,'('' Privileges successfully modified.'')')
+	ELSE
+	   WRITE (6,'('' ERROR: Cannot modify privileges.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER			! All finished with BULLUSER
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE ADD_ACL(ID,ACCESS,IER)
+C
+C  SUBROUTINE ADD_ACL
+C
+C  FUNCTION: Adds ACL to bulletin files.
+C
+C  PARAMETERS:
+C	ID - Character string containing identifier to add to ACL.
+C	ACCESS - Character string containing access controls to give to ID.
+C	IER - Return error from attempting to set ACL.
+C
+C  NOTE: The ID must be in the RIGHTS data base.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /ACL/ ACLENT
+	CHARACTER ACLENT*256
+
+	CHARACTER ID*(*),ACCESS*(*),NEWS_ACCESS*132
+
+	INCLUDE '($ACLDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	IER = SYS$PARSE_ACL('(IDENTIFIER='//ID//',ACCESS='
+     &	   //ACCESS//')',ACLENT,,)
+	IF (.NOT.IER) THEN
+	   IF (IER.EQ.SS$_NOSUCHID.AND.ADDID.AND.
+     &				INDEX(ACCESS,'C').EQ.0) THEN
+	      CALL GET_UAF(ID,USER,GROUP,ACCOUNT,FLAGS,IER)
+	      IF (.NOT.IER) THEN
+		 CALL ERRSNS(IDUMMY,IER)
+		 WRITE (6,'(
+     &		    '' ERROR: Specified username cannot be verified.'')')
+		 CALL SYS_GETMSG(IER)
+	         RETURN
+	      END IF
+	      IDENT = USER + ISHFT(GROUP,16)
+	      IER = SYS$ADD_IDENT(ID,%VAL(IDENT),,)
+	      IF (IER) THEN
+	         IER = SYS$PARSE_ACL('(IDENTIFIER='//ID//',ACCESS='
+     &	           //ACCESS//')',ACLENT,,)
+	      END IF
+	   END IF
+	END IF
+	IF (.NOT.IER) RETURN
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_ADDACLENT,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IF (INDEX(ACCESS,'C').GT.0.AND.INDEX(ACCESS,'W').EQ.0) THEN
+	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,BULLUSER_FILE(:TRIM(
+     &		   BULLUSER_FILE)),%VAL(ACL_ITMLST),,,)
+	   RETURN
+	END IF
+
+	IF (INDEX(FOLDER1,'.').GT.0) THEN
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,NEWS_ACCESS(FOLDER1_DESCRIP)
+     &	      ,%VAL(ACL_ITMLST),,,)
+        ELSE
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,FOLDER1_FILE
+     &	      (:TRIM(FOLDER1_FILE))//'.BULLFIL',%VAL(ACL_ITMLST),,,)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DEL_ACL(ID,ACCESS,IER)
+C
+C  SUBROUTINE DEL_ACL
+C
+C  FUNCTION: Adds ACL to bulletin files.
+C
+C  PARAMETERS:
+C	ID - Character string containing identifier to add to ACL.
+C	ACCESS - Character string containing access controls to give to ID.
+C	IER - Return error from attempting to set ACL.
+C
+C  NOTE: The ID must be in the RIGHTS data base.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /ACL/ ACLENT
+	CHARACTER ACLENT*256
+
+	CHARACTER ID*(*),ACCESS*(*),NEWS_ACCESS*132
+
+	INCLUDE '($ACLDEF)'
+
+	IF (ID.NE.' ') THEN
+	   IER = SYS$PARSE_ACL('(IDENTIFIER='//ID//',ACCESS='
+     &	      //ACCESS//')',ACLENT,,)
+	   IF (.NOT.IER) RETURN
+
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_DELACLENT,%LOC(ACLENT))
+	   CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	ELSE
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(255,ACL$C_DELETEACL,%LOC(ACLENT))
+	   CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	END IF
+
+	IF (INDEX(ACCESS,'C').GT.0) THEN
+	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,BULLUSER_FILE(:TRIM(
+     &		   BULLUSER_FILE)),%VAL(ACL_ITMLST),,,)
+	   RETURN
+	END IF
+
+	IF (INDEX(FOLDER1,'.').GT.0) THEN
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,NEWS_ACCESS(FOLDER1_DESCRIP)
+     &	      ,%VAL(ACL_ITMLST),,,)
+        ELSE
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,FOLDER1_FILE
+     &	      (:TRIM(FOLDER1_FILE))//'.BULLFIL',%VAL(ACL_ITMLST),,,)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CREATE_FOLDER
+C
+C  SUBROUTINE CREATE_FOLDER
+C
+C  FUNCTION: Creates a new bulletin folder.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	DATA REMOTE_SET /.FALSE./
+
+	COMMON /BULL_CUSTOM/ BULL_CUSTOM
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	DIMENSION LAST(2,FOLDER_MAX)
+	INTEGER*2 LAST2(4,FOLDER_MAX)
+	EQUIVALENCE (LAST,LAST2)
+
+	CHARACTER RESPONSE*4
+
+	IF (CLI$PRESENT('NEWS')) THEN
+	   CALL CREATE_NEWS_FOLDER
+	   RETURN
+	END IF
+
+	IF (.NOT.SETPRV_PRIV().AND.(CLI$PRESENT('NEEDPRIV').OR.
+     &		BTEST(BULL_CUSTOM,0))) THEN
+	   WRITE(6,'('' ERROR: CREATE is a privileged command.'')')
+	   RETURN
+	END IF
+
+	IER = CLI$GET_VALUE('CREATE_FOLDER',FOLDER,LEN_T) ! Get folder name
+	CALL STR$UPCASE(FOLDER,FOLDER)
+
+	IF (LEN_T.GT.44) THEN
+	   WRITE(6,'('' ERROR: Folder name must be < 45 characters.'')')
+	   RETURN
+	END IF
+
+	IF (.NOT.SETPRV_PRIV().AND.(CLI$PRESENT('ALWAYS').OR.
+     &	     CLI$PRESENT('NOTIFY').OR.CLI$PRESENT('READNEW').OR.
+     &	     CLI$PRESENT('BRIEF').OR.CLI$PRESENT('SYSTEM'))) THEN
+	   WRITE (6,'('' ERROR: Privileged qualifier specified.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('NODE')) THEN	! Remote node specified?
+	   IER = CLI$GET_VALUE('NODE',FOLDER_BBOARD,LEN_B) ! Get node name
+	   FOLDER_BBOARD = '::'//FOLDER_BBOARD(:LEN_B)
+	   FOLDER1_BBOARD = FOLDER_BBOARD
+	   IF (.NOT.CLI$GET_VALUE('REMOTENAME',FOLDER1,LEN_P)) THEN
+	      FOLDER1 = FOLDER
+	   ELSE IF (LEN_P.GT.40) THEN
+	      WRITE (6,'('' ERROR: REMOTENAME cannot be longer '',
+     &			 ''than 40 characters.'')')
+	   END IF
+	   FOLDER1_NUMBER = FOLDER_MAX
+	   CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	   IF (IER.NE.0) THEN
+	    WRITE (6,'('' ERROR: Folder not accessible on remote node.'')')
+	    RETURN
+	   ELSE IF (CLI$PRESENT('SYSTEM').AND.
+     &				.NOT.BTEST(FOLDER1_FLAG,2)) THEN
+	    WRITE (6,'('' ERROR: /SYSTEM not allowed as remote node'',
+     &			'' is not SYSTEM folder.'')')
+	    RETURN
+	   END IF
+	END IF
+
+	LENDES = 0
+	DO WHILE (LENDES.EQ.0)
+	   IF (CLI$PRESENT('DESCRIPTION')) THEN		! DESCRIPTION specified?
+	      IER = CLI$GET_VALUE('DESCRIPTION',FOLDER_DESCRIP,LENDES)
+	   ELSE
+	      WRITE (6,'('' Enter one line description of folder.'')')
+	      CALL GET_LINE(FOLDER_DESCRIP,LENDES)	! Get input line
+	      FOLDER_DESCRIP = FOLDER_DESCRIP(:LENDES)	! End fill with spaces
+	   END IF
+	   IF (LENDES.LE.0) THEN
+	      WRITE (6,'('' Aborting folder creation.'')')
+	      RETURN
+	   ELSE IF (LENDES.GT.80) THEN		! If too many characters
+	      WRITE(6,'('' ERROR: folder must be < 80 characters.'')')
+	      RETURN
+	   END IF
+	END DO
+
+	CALL OPEN_BULLFOLDER		! Open folder file
+	READ (7,IOSTAT=IER,KEY=FOLDER,KEYID=0)
+					! See if folder exists
+
+	IF (IER.EQ.0) THEN
+	   WRITE (6,'('' ERROR: Specified folder already exists.'')')
+	   GO TO 1000
+	END IF
+
+	IF (CLI$PRESENT('OWNER')) THEN
+	   IF (.NOT.SETPRV_PRIV().AND..NOT.CLI$PRESENT('ID')) THEN
+	      WRITE (6,'('' ERROR: /OWNER requires privileges.'')')
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   ELSE
+	      CALL CLI$GET_VALUE('OWNER',FOLDER1_OWNER,LEN_P)
+	      IF (LEN_P.GT.12) THEN
+	         WRITE (6,'('' ERROR: Folder owner name must be'',
+     &		        '' no more than 12 characters long.'')')
+	         CALL CLOSE_BULLFOLDER
+	         RETURN
+	      ELSE IF (CLI$PRESENT('ID')) THEN
+		 IER = CHKPRO(FOLDER1_OWNER)
+	         IF (.NOT.IER) THEN
+	            WRITE (6,'('' ERROR: ID not valid.'')')
+	            CALL CLOSE_BULLFOLDER
+	            RETURN
+		 END IF
+	      ELSE
+	         CALL GET_UAF
+     &		   (FOLDER1_OWNER,USERB1,GROUPB1,ACCOUNTB1,FLAGS,IER)
+	         IF (.NOT.IER) THEN
+	            WRITE (6,'('' ERROR: Owner not valid username.'')')
+	            CALL CLOSE_BULLFOLDER
+	            RETURN
+		 END IF
+	      END IF
+	      FOLDER_OWNER = FOLDER1_OWNER
+	   END IF
+	ELSE
+	   FOLDER_OWNER = USERNAME		! Get present username
+	   FOLDER1_OWNER = FOLDER_OWNER		! Save for later
+	END IF
+
+	FOLDER_SET = .TRUE.
+
+	CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+			! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD,GROUP)
+
+C
+C  Folder file is placed in the directory FOLDER_DIRECTORY.
+C  The file prefix is the name of the folder.
+C
+
+	FD_LEN = TRIM(FOLDER_DIRECTORY)
+	IF (FD_LEN.EQ.0) THEN
+	 WRITE (6,'('' ERROR: System programmer has disabled folders.'')')
+	 GO TO 910
+	ELSE
+	 FOLDER_FILE = FOLDER_DIRECTORY(:FD_LEN)//FOLDER
+	END IF
+
+	OPEN (UNIT=2,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Cannot create folder directory file.'')')
+	   CALL ERRSNS(IDUMMY,IER)
+	   CALL SYS_GETMSG(IER)
+	   GO TO 910
+	END IF
+
+	OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     1	 //'.BULLFIL',STATUS='NEW',
+     1	 ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     1	 FORM='UNFORMATTED',IOSTAT=IER)
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Cannot create folder message file.'')')
+	   CALL ERRSNS(IDUMMY,IER)
+	   CALL SYS_GETMSG(IER)
+	   GO TO 910
+	END IF
+
+	FOLDER_FLAG = 0
+
+	IF (CLI$PRESENT('PRIVATE').OR.CLI$PRESENT('SEMIPRIVATE')) THEN
+				! Will folder have access limitations?
+	   FOLDER1_FILE = FOLDER_FILE
+	   CLOSE (UNIT=1)
+	   CLOSE (UNIT=2)
+	   FOLDER1 = FOLDER	! Save for ADD_ACL
+	   IF (CLI$PRESENT('SEMIPRIVATE')) THEN
+	      CALL ADD_ACL('*','R',IER)
+	   ELSE
+	      CALL ADD_ACL('*','NONE',IER)
+	   END IF
+	   CALL ADD_ACL(FOLDER_OWNER,'R+W+C',IER)
+	   OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     1	    //'.BULLDIR',STATUS='OLD',IOSTAT=IER1)
+	   OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     1	    //'.BULLFIL',STATUS='OLD',IOSTAT=IER1)
+	   IF (.NOT.IER) THEN
+	      WRITE(6,
+     &	      '('' ERROR: Cannot create private folder using ACLs.'')')
+	      CALL SYS_GETMSG(IER)
+	      GO TO 910
+	   END IF
+	   FOLDER_FLAG = IBSET(FOLDER_FLAG,0)
+	END IF
+
+	IER = 0
+	LAST_NUMBER = 1
+	DO WHILE (IER.EQ.0.AND.LAST_NUMBER.LT.FOLDER_MAX-1)
+	   READ (7,IOSTAT=IER,KEY=LAST_NUMBER,KEYID=1)
+	   LAST_NUMBER = LAST_NUMBER + 1
+	END DO
+
+	IF (IER.EQ.0) THEN
+	 WRITE (6,'('' ERROR: Folder limit of '',I,'' has been reached.'')')
+     &			FOLDER_MAX
+	 WRITE (6,'('' Unable to add specified folder.'')')
+	 GO TO 910
+	ELSE
+	   FOLDER1_NUMBER = LAST_NUMBER - 1
+	END IF
+
+	IF (.NOT.CLI$PRESENT('NODE')) THEN
+	   FOLDER_BBOARD = 'NONE'
+	   IF (REMOTE_SET) CLOSE (UNIT=REMOTE_UNIT)
+	   REMOTE_SET = .FALSE.
+	   FOLDER_BBEXPIRE = 14
+	   F_NBULL = 0
+	   NBULL = 0
+	   F_NEWEST_BTIM(1) = 0
+	   F_NEWEST_BTIM(2) = 0
+	   F_NEWEST_NOSYS_BTIM(1) = 0
+	   F_NEWEST_NOSYS_BTIM(2) = 0
+	   F_EXPIRE_LIMIT = 0
+	   FOLDER_NUMBER = FOLDER1_NUMBER
+	ELSE
+	   CLOSE (UNIT=1,STATUS='DELETE')
+	   CLOSE (UNIT=2,STATUS='DELETE')
+	   IF (FOLDER1.NE.FOLDER) THEN	! Different remote folder name?
+	      REMOTE_SET = .FALSE.
+    	      CALL OPEN_BULLDIR		! If so, store name in directory file
+	      BULLDIR_HEADER(13:) = FOLDER1
+	      CALL WRITEDIR_NOCONV(0,IER)
+	      CALL CLOSE_BULLDIR
+	      FOLDER1_BBOARD = FOLDER1_BBOARD(:LEN_B+2)//'*'
+	      FOLDER1 = FOLDER
+	   END IF
+	   REMOTE_SET = .TRUE.
+	   IF (BTEST(FOLDER1_FLAG,0)) FOLDER_FLAG = IBSET(FOLDER_FLAG,0)
+	   FOLDER1_FLAG = FOLDER_FLAG
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP
+	   FOLDER_COM = FOLDER1_COM
+	   NBULL = F_NBULL
+	END IF
+
+	FOLDER_NAME = FOLDER
+	FOLDER_OWNER = FOLDER1_OWNER
+
+	MAILTO = 0
+	I = INDEX(FOLDER_DESCRIP,'<')
+	J = INDEX(FOLDER_DESCRIP,'>')
+	IF (I.GT.0.AND.J.GT.I.AND.(INDEX(FOLDER_DESCRIP(I:),'@').LT.1.OR.
+     &	    INDEX(FOLDER_DESCRIP(I:),'@').GT.J-I+1).AND.NEWS_FEED()) THEN
+           FOLDER_FLAG = IBSET(FOLDER_FLAG,4)
+	   I = INDEX(FOLDER_DESCRIP,'[')
+	   J = INDEX(FOLDER_DESCRIP,']')
+	END IF
+
+	IF (I.GT.0.AND.J.GT.I.AND.
+     &	       (INDEX(FOLDER_DESCRIP(I:),'@').GT.1.AND.
+     &	       INDEX(FOLDER_DESCRIP(I:),'@').LT.J-I+1)) THEN
+	   MAILTO = 1
+	END IF
+
+	IF (CLI$PRESENT('SYSTEM')) FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	IF (CLI$PRESENT('ID')) FOLDER_FLAG = IBSET(FOLDER_FLAG,6)
+	IF (CLI$PRESENT('ALWAYS')) FOLDER_FLAG = IBSET(FOLDER_FLAG,7)
+	IF (CLI$PRESENT('POST_ONLY')) FOLDER_FLAG = IBSET(FOLDER_FLAG,10)
+	IF (CLI$PRESENT('ADD_ONLY')) FOLDER_FLAG = IBSET(FOLDER_FLAG,11)
+	IF (CLI$PRESENT('COMPRESS')) FOLDER_FLAG = IBSET(FOLDER_FLAG,12)
+
+	IF (I.GT.0.AND.J.GT.I.AND..NOT.NEWS_FEED().AND.MAILTO.EQ.0
+     &	    .AND..NOT.BTEST(FOLDER_FLAG,11)
+     &	    .AND..NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	   CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Have you specified '//
+     &		'an email address in the description? (default=N) ')
+	   IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') MAILTO = 1
+	END IF
+
+	IF (MAILTO.EQ.1.AND..NOT.BTEST(FOLDER_FLAG,11).AND.
+     &	    .NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	   WRITE (6,'('' A mailing address has been specified.'')')
+	   CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Will messages be '//
+     &		'sent to and received from this address? (default=N) ')
+	   IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') THEN
+	      MAILTO = 2
+	      WRITE (6,'('' SET POST_ONLY will be issued.'')')
+	   ELSE
+	      MAILTO = 3
+	      WRITE (6,'('' SET ADD_ONLY will be issued.'')')
+	   END IF
+	END IF
+
+	CALL WRITE_FOLDER_FILE(IER)
+	CALL MODIFY_SYSTEM_LIST(0)
+
+	CLOSE (UNIT=1)
+	CLOSE (UNIT=2)
+
+	NOTIFY = 0
+	READNEW = 0
+	BRIEF = 0
+	IF (CLI$PRESENT('NOTIFY')) NOTIFY = 1
+	IF (CLI$PRESENT('READNEW')) READNEW = 1
+	IF (CLI$PRESENT('SHOWNEW')) BRIEF = 1
+	IF (CLI$PRESENT('BRIEF')) THEN
+	   BRIEF = 1
+	   READNEW = 1
+	END IF
+	CALL SET_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+
+	WRITE (6,'('' Folder is now set to '',A)')
+     &		FOLDER(:TRIM(FOLDER))//'.'
+
+	IF (CLI$GET_VALUE('COPY',FOLDER1,FLEN).NE.%LOC(CLI$_ABSENT)) THEN
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' Unable to copy folder settings.'')')
+	   ELSE
+	      CALL OPEN_BULLINF_SHARED
+	      IER = 0
+	      DO WHILE (IER.EQ.0)
+		 DO WHILE (REC_LOCK(IER))
+		    READ (9,IOSTAT=IER) TEMP_USER,LAST
+		 END DO
+		 IF (IER.EQ.0) THEN
+		    LU = TRIM(TEMP_USER)
+		    I = MAX(LU,2) - 1
+		    IF (.NOT.BTEST(ICHAR(TEMP_USER(I:I)),7)) THEN
+		       LAST(1,FOLDER1_NUMBER+1) = LAST(1,FOLDER_NUMBER+1)
+		       LAST(2,FOLDER1_NUMBER+1) = LAST(2,FOLDER_NUMBER+1)
+		       REWRITE (9,IOSTAT=IER) TEMP_USER,LAST 
+		    END IF
+		 END IF
+	      END DO
+	      CALL CLOSE_BULLINF
+	      CALL OPEN_BULLUSER_SHARED
+	      CALL READ_USER_FILE_HEADER(IER)
+	      CALL READ_USER_FILE(IER)
+	      DO WHILE (IER.EQ.0)
+	         IF (TEST2(SET_FLAG,FOLDER1_NUMBER)) THEN
+		    CALL SET2(SET_FLAG,FOLDER_NUMBER)
+		 ELSE
+		    CALL CLR2(SET_FLAG,FOLDER_NUMBER)
+		 END IF
+	         IF (TEST2(BRIEF_FLAG,FOLDER1_NUMBER)) THEN
+		    CALL SET2(BRIEF_FLAG,FOLDER_NUMBER)
+		 ELSE
+		    CALL CLR2(BRIEF_FLAG,FOLDER_NUMBER)
+		 END IF
+	         IF (TEST2(NOTIFY_FLAG,FOLDER1_NUMBER)) THEN
+		    CALL SET2(NOTIFY_FLAG,FOLDER_NUMBER)
+		 ELSE
+		    CALL CLR2(NOTIFY_FLAG,FOLDER_NUMBER)
+		 END IF
+	         REWRITE(4) TEMP_USER//USER_ENTRY(13:)
+	         CALL READ_USER_FILE(IER)
+	      END DO
+	      CALL CLOSE_BULLUSER
+	   END IF
+	END IF
+
+	GO TO 1000
+
+910	WRITE (6,'('' Aborting folder creation.'')')
+	IF (FOLDER_NUMBER.EQ.0) FOLDER_SET = .FALSE.
+	CLOSE (UNIT=1,STATUS='DELETE')
+	CLOSE (UNIT=2,STATUS='DELETE')
+
+1000	CALL CLOSE_BULLFOLDER
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	RETURN
+
+	END
+
+
+
+	INTEGER FUNCTION CHKPRO(INPUT)
+C
+C 	Description:
+C		Parse given identify into binary ACL format.
+C		Call SYS$CHKPRO to check if present process has read
+C		access to an object if the object's protection is the ACL.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER ACL*256
+	CHARACTER*(*) INPUT
+
+	INCLUDE '($CHPDEF)'
+
+	CHKPRO = SYS$PARSE_ACL('(IDENTIFIER='//INPUT(:TRIM(INPUT))//
+     &		',ACCESS=R)',ACL,,)	! Convert to ACL into binary format
+	IF (.NOT.CHKPRO) RETURN		! Exit if can't
+
+	FLAGS = CHP$M_READ		! Specify read access checking
+
+	CALL INIT_ITMLST		! Initialize item list
+	CALL ADD_2_ITMLST(ICHAR(ACL(:1)),CHP$_ACL,%LOC(ACL(1:1)))
+	CALL ADD_2_ITMLST(4,CHP$_FLAGS,%LOC(FLAGS))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	CHKPRO = SYS$CHKPRO(%VAL(ACL_ITMLST))	! Check if process has the
+						! rights-id assigned to it
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CREATE_NEWS_FOLDER
+C
+C  SUBROUTINE CREATE_NEWS_FOLDER
+C
+C  FUNCTION: Creates a new newsgroup.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	EDITIT = (CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.
+     &           (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))
+
+	IER = CLI$GET_VALUE('CREATE_FOLDER',FOLDER1_NAME,LEN_F)
+	CALL LOWERCASE(FOLDER1_NAME)
+
+	LEN_P = 0
+
+	IF (CLI$PRESENT('FILESPEC')) THEN
+	   IER = CLI$GET_VALUE('FILESPEC',BULL_PARAMETER,LEN_P)
+	   CALL DISABLE_PRIVS
+	   OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
+	   CALL ENABLE_PRIVS	! Reset SYSPRV privileges
+	END IF
+C
+C  If file specified in command, read file.
+C  Else, read  from the terminal.
+C
+
+	IF (EDITIT) THEN			! If /EDIT specified
+	   IF (LEN_P.EQ.0) THEN			! If no file param specified
+	      CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 DISPOSE='DELETE',ERR=910,FORM='FORMATTED')
+	      LEN_P = 1
+	   ELSE
+	      CLOSE (UNIT=3)
+	      CALL MAILEDIT(BULL_PARAMETER(:LEN_P),'SYS$LOGIN:BULL.SCR')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 DISPOSE='DELETE',ERR=910,FORM='FORMATTED')
+	   END IF
+	ELSE IF (LEN_P.EQ.0) THEN			! If file param
+	   OPEN (UNIT=3,STATUS='SCRATCH',FILE='SYS$LOGIN:BULL.SCR',
+     &		FORM='FORMATTED',RECL=LINE_LENGTH) ! Temp file to save message
+	   WRITE (6,1000)			! Request input from terminal
+1000	   FORMAT (' Enter newsgroup description:',
+     &		   ' End with ctrl-z, cancel with ctrl-c')
+	   ILEN = 0
+	   ICOUNT = 0
+	   DO WHILE (ILEN.GE.0)			! Input until no more input
+	      CALL GET_LINE(INPUT,ILEN)		! Get input line
+	      IF (ILEN.GT.LINE_LENGTH) THEN	! Input line too long
+		 WRITE(6,'('' ERROR: Input line length > '',I,
+     &			''.  Reinput:'')') LINE_LENGTH
+	      ELSE IF (ILEN.GE.0) THEN		! If good input line entered
+		 WRITE(3,2010) INPUT(:ILEN)	! Save line in scratch file
+2010	         FORMAT(A)
+		 ICOUNT = ICOUNT + ILEN
+	      END IF
+	   END DO
+	   IF (ILEN.EQ.-1) GO TO 910		! CTRL_C entered, error out
+	   IF (ICOUNT.EQ.0) GO TO 910		! No lines entered, error out
+	ENDIF
+
+	REWIND (UNIT=3)
+
+	CALL NEWS_POST('newgroup '//FOLDER1_NAME(:LEN_F),.TRUE.,IER,
+     &		       'Adding newsgroup.')
+	CLOSE (UNIT=3)
+
+	RETURN
+
+920	WRITE(6,1020)
+1020	FORMAT (' ERROR: Unable to open specified file.')
+	CALL ENABLE_PRIVS
+	RETURN
+
+910	WRITE(6,1010)
+1010	FORMAT (' No news group was added.')
+	CLOSE (UNIT=3)
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE INIT_COMPRESS
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*2 MAP(159),UNMAP(0:254)
+
+	DATA MAP/
+     &	'  ', 'e ', 'th', ' t', 's ', ' a', 'in', 't ', 'er', 'he', 'on',
+     &	'at', ': ', 're', 'an', 'it', 'ti', 'n ', ' i', ' o', 'es', 'ne',
+     &	'te', 'd ', ' s', 'en', 'ed', 'is', 'ic', 'y ', 'st', 'ar', 'or',
+     &	', ', ' w', 'al', 'ou', 'ha', 'du', 'le', 'r ', 'nt', '.e', 'nd',
+     &	'to', 'f ', 've', 'ng', 'ct', ' p', 'o ', 'me', 'om', 'of', '. ',
+     &	' c', 'io', 'ri', 'ca', 'se', ' m', ' b', 'ta', 'co', 'el', 'si',
+     &	'as', 'hi', 'de', ' f', 'l ', 'ec', 'll', 'ro', 'et', 'a ', ' d',
+     &	'ni', ' e', 'ea', 'no', 'li', 'ch', 's.', 'ra', 'ma', 'ce', 'sc',
+     &	'ns', 'g ', 'ss', 'nc', 'us', 'be', ' h', '> ', 'h ', 'ac', 'os',
+     &	'ci', 'bl', 'ph', 'rt', ' r', 'ot', ' I', 'tr', 'ut', ' n', 'la',
+     &	'cs', 'ly', 'pr', 'wa', 'ws', 'oo', 'pe', 'ag', 'ys', 'so', 'ie',
+     &	'ur', 'un', ' (', 'po', 'fo', 'em', ' l', 'm ', 'ho', 'lo', 'wi',
+     &	' T', 'e.', 'im', 'di', 'ia', '.c', 'pa', 'ge', 'ga', 'ee', 'rs',
+     &	'pi', 'su', 'Th', 'il', 'ai', 'wh', 'ol', 'ul', 'gr', 'ow', 'u ',
+     &	'iv', 'pl', 'ab', 'am', 'mo'/
+
+	CHARACTER*1 A(0:127,0:127)
+	CHARACTER*2 B
+
+	CHARACTER*(*) IN,OUT
+	CHARACTER*255 T
+
+	DO I=0,127
+	   DO J=0,127
+	     A(J,I) = ' '
+	   END DO
+	END DO
+
+	UNMAP(0) = '  '
+        DO I=1,254
+           UNMAP(I) = CHAR(255)//CHAR(255)
+	END DO
+	
+	J = 1
+	DO I=1,8
+	   J = J + 1
+	   B = MAP(J)
+	   UNMAP(I) = B
+	   A(ICHAR(B(:1)),ICHAR(B(2:2))) = CHAR(I)
+	END DO
+	DO I=10,31
+	   J = J + 1
+	   B = MAP(J)
+	   UNMAP(I) = B
+	   A(ICHAR(B(:1)),ICHAR(B(2:2))) = CHAR(I)
+	END DO
+	DO I=127,254
+	   J = J + 1
+	   B = MAP(J)
+	   UNMAP(I) = B
+	   A(ICHAR(B(:1)),ICHAR(B(2:2))) = CHAR(I)
+	END DO
+
+	RETURN
+
+	ENTRY COMPRESS(IN,OUT,O)
+
+	L = LEN(IN)
+	O = 1
+	K = 1
+	DO WHILE (K.LT.L)
+	   IF (ICHAR(IN(K:K)).GT.126) IN(K:K) = ' '
+	   IF (ICHAR(IN(K+1:K+1)).GT.126) IN(K+1:K+1) = ' '
+	   T(O:O) = A(ICHAR(IN(K:)),ICHAR(IN(K+1:)))
+	   IF (T(O:O).NE.' ') THEN
+	      K = K + 2
+	      O = O + 1
+	   ELSE IF (L.GT.K+2.AND.IN(K:K).EQ.IN(K+1:K+1).AND.
+     &		    IN(K:K+1).EQ.IN(K+2:K+3)) THEN
+	      C = 4
+	      K = K + 4
+	      DO WHILE (K.LE.L.AND.IN(K:K).EQ.IN(K-1:K-1))
+		 C = C + 1
+		 K = K + 1
+	      END DO
+	      T(O:O+2) = CHAR(255)//CHAR(C)//IN(K-1:K-1)
+	      O = O + 3
+	   ELSE IF (IN(K:K+1).EQ.'  ') THEN
+	      K = K + 2
+	      T(O:O) = CHAR(0)
+	      O = O + 1
+	   ELSE
+	      T(O:O) = IN(K:K)
+	      IF (ICHAR(T(O:O)).LT.9.OR.(ICHAR(T(O:O)).GT.9.AND.
+     &		 ICHAR(T(O:O)).LT.32)) T(O:O) = ' '
+	      K = K + 1
+	      O = O + 1
+	   END IF
+	END DO
+	IF (K.EQ.L) THEN
+	   T(O:O) = IN(K:K)
+	ELSE
+	   O = O - 1
+	END IF
+
+	OUT = T
+
+	RETURN
+
+	ENTRY UNCOMPRESS(IN,OUT,O)
+
+	L = LEN(IN)
+	O = 0
+	I = 1
+	DO WHILE (I.LE.L)
+	   J = ICHAR(IN(I:I))
+	   IF (J.EQ.255) THEN
+	      DO J=1,ICHAR(IN(I+1:I+1))
+	         O = O + 1
+	         T(O:O) = IN(I+2:I+2)
+	      END DO
+	      I = I + 3
+           ELSE
+	      B = UNMAP(J)
+	      IF (B.EQ.CHAR(255)//CHAR(255)) THEN
+	         O = O + 1
+                 T(O:O) = IN(I:I)
+	      ELSE
+	         O = O + 2
+	         T(O-1:O) = B
+	      END IF
+	      I = I + 1
+	   END IF
+	END DO
+
+	OUT = T(:O)
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin5.for b/decus/vmslt00a/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..bc7c3a7346b93bbec4dab25713f606eb99f8e8dc
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin5.for
@@ -0,0 +1,2516 @@
+C
+C  BULLETIN5.FOR, Version 3/5/98
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+C
+	SUBROUTINE SET_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+C
+C  SUBROUTINE SET_FOLDER_DEFAULT
+C
+C  FUNCTION: Sets flag defaults for specified folder
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_NEGATED
+
+	IF (REMOTE_SET.GE.3) THEN
+	   CALL SET_NEWS_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+	   RETURN
+        ELSE IF (FOLDER_NUMBER.LT.0) THEN
+	   WRITE (6,'('' ERROR: Command is invalid for this folder.'')')
+	   RETURN
+	END IF
+
+	ALL = .FALSE.
+	DEFAULT = 0
+	NODEFAULT = 0
+
+	IF (INCMD(:3).EQ.'SET') THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	      WRITE (6,'(
+     &           '' ERROR: Privileges needed for changing defaults.'')')
+	      RETURN
+	   END IF
+	   ALL = CLI$PRESENT('ALL')
+	   DEFAULT = CLI$PRESENT('DEFAULT')
+	   NODEFAULT = CLI$PRESENT('NODEFAULT')
+	   CALL OPEN_BULLUSER_SHARED
+	   IF (CLI$PRESENT('PERMANENT')) THEN
+	      CALL SET_PERM(NOTIFY,READNEW,BRIEF)
+	   ELSE IF (CLI$PRESENT('NOPERMANENT')) THEN
+	      IF (NOTIFY.GE.0) CALL SET_PERM(0,-1,-1)
+	      IF (READNEW.GE.0.OR.BRIEF.GE.0) CALL SET_PERM(-1,0,0)
+	   END IF
+	ELSE
+	   CALL OPEN_BULLUSER_SHARED
+	END IF
+
+	CALL READ_USER_FILE_HEADER(IER)
+	IF (NODEFAULT) THEN
+	   IF (NOTIFY.NE.-1) CALL CLR2(NOTIFY_FLAG_DEF,FOLDER_NUMBER)
+	   IF (READNEW.NE.-1.OR.BRIEF.NE.-1) THEN
+	      CALL CLR2(SET_FLAG_DEF,FOLDER_NUMBER)
+	      CALL CLR2(BRIEF_FLAG_DEF,FOLDER_NUMBER)
+	   END IF
+	   REWRITE(4) USER_HEADER
+	ELSE IF (DEFAULT.EQ.0.OR.DEFAULT) THEN
+	   IF (NOTIFY.EQ.0) CALL CLR2(NOTIFY_FLAG_DEF,FOLDER_NUMBER)
+	   IF (NOTIFY.EQ.1) CALL SET2(NOTIFY_FLAG_DEF,FOLDER_NUMBER)
+	   IF (READNEW.EQ.0) CALL CLR2(SET_FLAG_DEF,FOLDER_NUMBER)
+	   IF (READNEW.EQ.1) CALL SET2(SET_FLAG_DEF,FOLDER_NUMBER)
+	   IF (BRIEF.EQ.0) CALL CLR2(BRIEF_FLAG_DEF,FOLDER_NUMBER)
+	   IF (BRIEF.EQ.1) CALL SET2(BRIEF_FLAG_DEF,FOLDER_NUMBER)
+	   REWRITE(4) USER_HEADER
+	END IF
+
+	IF (ALL.OR.(BRIEF.NE.-1.AND.NOTIFY.NE.-1.AND.READNEW.NE.-1)) THEN
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0)
+	      IF (TEMP_USER(:1).NE.'*'.AND.TEMP_USER(:1).NE.':') THEN
+	         IF (NOTIFY.EQ.0) CALL CLR2(NOTIFY_FLAG,FOLDER_NUMBER)
+	         IF (NOTIFY.EQ.1) CALL SET2(NOTIFY_FLAG,FOLDER_NUMBER)
+	         IF (READNEW.EQ.0) CALL CLR2(SET_FLAG,FOLDER_NUMBER)
+	         IF (READNEW.EQ.1) CALL SET2(SET_FLAG,FOLDER_NUMBER)
+	         IF (BRIEF.EQ.0) CALL CLR2(BRIEF_FLAG,FOLDER_NUMBER)
+	         IF (BRIEF.EQ.1) CALL SET2(BRIEF_FLAG,FOLDER_NUMBER)
+	         REWRITE(4) TEMP_USER//USER_ENTRY(13:)
+	      END IF
+	      CALL READ_USER_FILE(IER)
+	   END DO
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE READ_PERM
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULL_PERM/ SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	DIMENSION SET_PERM_FLAG(FLONG)
+	DIMENSION BRIEF_PERM_FLAG(FLONG)
+	DIMENSION NOTIFY_PERM_FLAG(FLONG)
+
+	COMMON /FLAG_ACCESS/ FLAG_ACCESS
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*PERM',IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	END DO
+
+	IF (IER.NE.0) THEN
+	   DO I=1,FLONG
+	      SET_PERM_FLAG(I) = 0
+	      BRIEF_PERM_FLAG(I) = 0
+	      NOTIFY_PERM_FLAG(I) = 0
+	   END DO
+	   BRIEF_PERM_FLAG(1) = 1	! SHOWNEW permanent for GENERAL folder
+	   WRITE (4,IOSTAT=IER)
+     &		'*PERM       ',
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	   CALL READ_USER_FILE_HEADER(IER)
+	   IF (.NOT.TEST2(SET_FLAG_DEF,0)) THEN
+	      CALL SET2(BRIEF_FLAG_DEF,0)
+	      REWRITE(4) USER_HEADER
+	   END IF
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0)
+	      IF (TEMP_USER(:1).NE.'*'.AND.TEMP_USER(:1).NE.':') THEN
+		 IF (.NOT.TEST2(SET_FLAG,0)) THEN
+		    CALL SET2(BRIEF_FLAG,0)
+	            REWRITE(4) TEMP_USER//USER_ENTRY(13:)
+	         END IF
+	      END IF
+	      CALL READ_USER_FILE(IER)
+	   END DO
+	ELSE
+	   UNLOCK 4
+	END IF
+
+	RETURN
+
+	ENTRY SET_PERM(NOTIFY,READNEW,BRIEF)
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*PERM',IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	END DO
+
+	IF (NOTIFY.EQ.0) CALL CLR2(NOTIFY_PERM_FLAG,FOLDER_NUMBER)
+	IF (NOTIFY.EQ.1) CALL SET2(NOTIFY_PERM_FLAG,FOLDER_NUMBER)
+	IF (READNEW.EQ.0) CALL CLR2(SET_PERM_FLAG,FOLDER_NUMBER)
+	IF (READNEW.EQ.1) CALL SET2(SET_PERM_FLAG,FOLDER_NUMBER)
+	IF (BRIEF.EQ.0) CALL CLR2(BRIEF_PERM_FLAG,FOLDER_NUMBER)
+	IF (BRIEF.EQ.1) CALL SET2(BRIEF_PERM_FLAG,FOLDER_NUMBER)
+
+	REWRITE (4,IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+
+	RETURN
+
+	ENTRY SET_USER_FLAG(NOTIFY,READNEW,BRIEF)
+
+	IF (.NOT.FLAG_ACCESS) THEN
+	   WRITE (6,'('' ERROR: Cannot set flags for protected'',
+     &	     '' folder without explicit access granted'',/,
+     &	     '' via SET ACCESS.  See HELP SET ACCESS for further''
+     &       '' information.'')')
+	   RETURN
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+ 	   IF (REMOTE_SET.EQ.3.AND.NOTIFY.EQ.1) THEN
+	      WRITE (6,'('' ERROR: NOTIFY is not valid for this folder.'')')
+	      RETURN
+	   END IF
+	   CALL NEWS_SET_USER_FLAG(NOTIFY,READNEW,BRIEF)
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLUSER_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*PERM',IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	END DO
+
+	CALL CLOSE_BULLUSER
+
+	IER = .TRUE.
+	IF (NOTIFY.EQ.0) THEN
+ 	   IF (TEST2(NOTIFY_PERM_FLAG,FOLDER_NUMBER)) THEN
+	      WRITE (6,'('' ERROR: NOTIFY is permanent for this folder.'')')
+	      RETURN
+	   ELSE
+	      CALL CHANGE_FLAG(0,4)
+	   END IF
+	ELSE IF (NOTIFY.EQ.1) THEN
+	   CALL CHANGE_FLAG(1,4)
+	   RETURN
+	ELSE IF (BRIEF.EQ.0.AND.READNEW.EQ.0.AND.
+     &	   (TEST2(SET_PERM_FLAG,FOLDER_NUMBER).OR.
+     &	   TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER))) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.0.AND.
+     &	   TEST2(SET_PERM_FLAG,FOLDER_NUMBER).AND.
+     &	   .NOT.TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER)) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.1.AND.
+     &	   (TEST2(SET_PERM_FLAG,FOLDER_NUMBER).XOR.
+     &	   TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER)))  THEN
+	   IER = .FALSE.
+	END IF
+
+	IF (IER) THEN
+	   IF (READNEW.GE.0) CALL CHANGE_FLAG(READNEW,2)
+	   IF (BRIEF.GE.0) CALL CHANGE_FLAG(BRIEF,3)
+	ELSE
+	   WRITE (6,'('' ERROR: PERMANENT flags exist for this folder.'')')
+	   WRITE (6,'('' Flags will be set to those permanent settings.'')')
+
+	   IF (TEST2(SET_PERM_FLAG,FOLDER_NUMBER)) THEN
+	      CALL CHANGE_FLAG(1,2)
+	   ELSE
+	      CALL CHANGE_FLAG(0,2)
+	   END IF
+
+	   IF (TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER)) THEN
+	      CALL CHANGE_FLAG(1,3)
+	   ELSE
+	      CALL CHANGE_FLAG(0,3)
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE REMOVE_FOLDER
+C
+C  SUBROUTINE REMOVE_FOLDER
+C
+C  FUNCTION: Removes a bulletin folder.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER RESPONSE*4,TEMP*80
+
+	IER = CLI$GET_VALUE('REMOVE_FOLDER',FOLDER1,LEN_T) ! Get folder name
+
+	IF (IER.EQ.%LOC(CLI$_ABSENT)) THEN
+	   IF (.NOT.FOLDER_SET) THEN
+	      WRITE (6,'('' ERROR: No folder specified.'')')
+	      RETURN
+	   ELSE
+	      FOLDER1 = FOLDER
+	   END IF
+	ELSE IF (LEN_T.GT.44) THEN
+	   WRITE(6,'('' ERROR: Folder name must be < 26 characters.'')')
+	   RETURN
+	END IF
+
+	CALL GET_INPUT_PROMPT(RESPONSE,LEN,
+     &   'Are you sure you want to remove folder '
+     &	 //FOLDER1(:TRIM(FOLDER1))//' (Y/N with N as default): ')
+	IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+	   WRITE (6,'('' Folder was not removed.'')')
+	   RETURN
+	END IF
+
+	IF (INDEX(FOLDER1,'.').GT.0) THEN
+	   CALL OPEN_BULLNEWS_SHARED
+	ELSE
+	   CALL OPEN_BULLFOLDER
+	END IF
+
+	CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)	! See if folder exists
+	CALL SET_FOLDER_FILE(1)
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: No such folder exists.'')')
+	   GO TO 1000
+	ELSE IF (INDEX(FOLDER1,'.').GT.0) THEN
+	   CALL REMOTE_REMOVE_FOLDER(IER)
+	   IF (.NOT.IER) GO TO 1000
+	END IF
+
+	IF (.NOT.FOLDER_ACCESS(USERNAME,FOLDER1_FLAG,FOLDER1_OWNER).OR.
+     &	     (FOLDER1_NUMBER.EQ.0.AND.FOLDER1_BBOARD(:2).NE.'::')) THEN
+	   WRITE (6,'('' ERROR: You are not able to remove the folder.'')')
+	   GO TO 1000
+	END IF
+
+	TEMP = FOLDER_FILE
+	FOLDER_FILE = FOLDER1_FILE
+
+	REMOTE_SET_SAVE = REMOTE_SET
+	REMOTE_SET = .FALSE.
+
+	IF (FOLDER1_BBOARD(:2).EQ.'::'.AND.BTEST(FOLDER1_FLAG,2)) THEN
+	   FLEN = TRIM(FOLDER1_BBOARD)
+	   IF (INDEX(FOLDER1_BBOARD,'*').GT.0) FLEN = FLEN - 1
+	   OPEN (UNIT=17,STATUS='UNKNOWN',IOSTAT=IER,
+     &		RECL=256,FILE=FOLDER1_BBOARD(3:FLEN)
+     &		//'::"TASK=BULLETIN1"')
+	   IF (IER.EQ.0) THEN		! Deregister remote SYSTEM folder
+	      IF (INDEX(FOLDER1_BBOARD,'*').GT.0) THEN
+	         CALL OPEN_BULLDIR
+	         CALL READDIR(0,IER)
+		 IF (IER.EQ.1) FOLDER1 = BULLDIR_HEADER(13:)
+		 CALL CLOSE_BULLDIR
+	      END IF
+	      WRITE (17,'(2A)',IOSTAT=IER) 1,FOLDER1	! Select folder
+	      IF (IER.EQ.0) READ(17,'(5A)',IOSTAT=IER)	! Throw away response
+	      IF (IER.EQ.0) WRITE(17,'(2A)',IOSTAT=IER) 14,0	! Deregister
+	      CLOSE (UNIT=17)
+	   END IF
+	END IF
+
+	TEMPSET = FOLDER_SET
+	FOLDER_SET = .TRUE.
+	CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD,GROUP)
+		! in case files don't exist and are created.
+	CALL OPEN_BULLDIR			! Remove directory file
+	CALL OPEN_BULLFIL			! Remove bulletin file
+	CALL CLOSE_BULLFIL_DELETE
+	CALL CLOSE_BULLDIR_DELETE
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+	FOLDER_FILE = TEMP
+	FOLDER_SET = TEMPSET
+
+	DELETE (7)
+
+	IF (FOLDER1_NUMBER.NE.0.OR.FOLDER1_BBOARD(:2).NE.'::') THEN
+		! Test is due to bug which changes folder number to zero
+	   TEMP_NUMBER = FOLDER_NUMBER
+	   FOLDER_NUMBER = FOLDER1_NUMBER
+	   TEMP_FLAG = FOLDER_FLAG
+	   IF (BTEST(FOLDER1_FLAG,2)) THEN
+	      FOLDER_FLAG = IBCLR(FOLDER1_FLAG,2)
+	      CALL MODIFY_SYSTEM_LIST(0)
+	   END IF
+	   CALL SET_FOLDER_DEFAULT(0,0,0)
+	   FOLDER_FLAG = TEMP_FLAG
+	   FOLDER_NUMBER = TEMP_NUMBER
+	END IF
+
+	WRITE (6,'('' Folder removed.'')')
+
+	IF (FOLDER.EQ.FOLDER1) THEN
+	   CALL CLOSE_BULLFOLDER
+	   FOLDER_SET = .FALSE.
+           FOLDER_NUMBER = 0
+           CALL SELECT_FOLDER(.FALSE.,IER)
+           WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &              FOLDER(:TRIM(FOLDER))
+	   RETURN
+	ELSE
+	   REMOTE_SET = REMOTE_SET_SAVE
+	END IF
+
+1000	CALL CLOSE_BULLFOLDER
+
+	RETURN
+
+	END
+
+
+	SUBROUTINE SELECT_FOLDER(OUTPUT,IER)
+C
+C  SUBROUTINE SELECT_FOLDER
+C
+C  FUNCTION: Selects the specified folder.
+C
+C  INPUTS:
+C	OUTPUT - Specifies whether status messages are outputted.
+C
+C  NOTES:
+C	FOLDER_NUMBER is used for selecting the folder.
+C	If FOLDER_NUMBER = -1, the name stored in FOLDER1 is used.
+C	If FOLDER_NUMBER = -2, the name stored in FOLDER1 is used,
+C	but the folder is not selected if it is remote.
+C	If the specified folder is on a remote node and does not have
+C	a local entry (i.e. specified via NODENAME::FOLDERNAME), then
+C	FOLDER_NUMBER is set to -1.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($RMSDEF)'
+	INCLUDE '($SSDEF)'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	DATA REMOTE_SET /.FALSE./
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	COMMON /HEADER/ HEADER
+
+	COMMON /READIT/ READIT
+
+	COMMON /FLAG_ACCESS/ FLAG_ACCESS
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /LAST_FOLDER/ LAST_FOLDER_NUMBER 
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	CHARACTER FSTATUS*4,FOLDER1_SAVE*44,NEWS_ACCESS*132
+
+	CHARACTER*80 LOCAL_FOLDER1_DESCRIP
+
+	DIMENSION FIRST_TIME(FLONG)	! Bit set for folder if folder has
+	DATA FIRST_TIME /FLONG*0/	! been selected before this.
+
+	DIMENSION OLD_NEWEST_BTIM(2)
+
+	DATA LAST_NEWS_GROUP/0/
+
+	CALL UPDATE_EXCLUDE
+
+	CALL UPDATE_USERINFO
+
+	COMMAND = (INCMD(:3).EQ.'ADD').OR.(INCMD(:3).EQ.'DEL').OR.
+     &		  (INCMD(:3).EQ.'DIR').OR.(INCMD(:3).EQ.'IND').OR.
+     &		  (INCMD(:3).EQ.'REP').OR.(INCMD(:3).EQ.'SEL').OR.
+     &		  (INCMD(:3).EQ.'SET').OR.(INCMD(:3).EQ.'SEA')
+
+	IF (.NOT.OUTPUT.OR.FOLDER_NUMBER.NE.-1.OR.COMMAND) THEN
+	   IF (OUTPUT) THEN			! Get folder name
+	      IER = CLI$GET_VALUE('SELECT_FOLDER',FOLDER1_NAME)
+	      FOLDER1 = FOLDER1_NAME
+	   END IF
+
+	   FLEN = TRIM(FOLDER1)		! Add GENERAL after :: if no
+	   IF (FLEN.GT.1) THEN		! name specified after the ::
+	      IF (FOLDER1(FLEN-1:FLEN).EQ.'::') THEN
+	         FOLDER1 = FOLDER1(:FLEN)//'GENERAL'
+	      END IF
+	   END IF
+
+	   IF (((IER.EQ.%LOC(CLI$_ABSENT).OR.FOLDER1.EQ.'GENERAL').AND.
+     &	    OUTPUT).OR.((FOLDER_NUMBER.EQ.0.OR.(FOLDER1.EQ.'GENERAL'.AND.
+     &	    FOLDER_NUMBER.LE.-1)).AND..NOT.OUTPUT)) THEN ! Select GENERAL
+	      FOLDER_NUMBER = 0
+	      FOLDER1 = 'GENERAL'
+	   END IF
+	END IF
+
+	REMOTE_TEST = 0
+	REMOTE_SET_NEW = 0
+
+	IF (SAVE_FOLDER_Q1.NE.0) THEN			! Have folder info
+	   FOLDER1_COM = FOLDER_COM
+	   IER = 0
+	   NEWS = INDEX(FOLDER1,'.').GT.0.OR.(FOLDER1(:1).GE.'a'.AND.
+     &					   FOLDER1(:1).LE.'z')
+	   IF (NEWS.AND.BTEST(FOLDER1_FLAG,8)) REMOTE_SET_NEW = 4
+	ELSE
+	   NEWS = ((INDEX(FOLDER1,'.').GT.0.OR.(FOLDER1(:1).GE.'a'.AND.
+     &		FOLDER1(:1).LE.'z')).AND.(FOLDER_NUMBER.LE.-1.OR.OUTPUT))
+     &		.OR.(FOLDER_NUMBER.GT.1000.AND..NOT.OUTPUT)
+	   IF (NEWS.AND.
+     &		SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) THEN
+	      CALL OPEN_BULLNEWS_SHARED		! Go find folder
+	      READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1) NEWS_FOLDER1_COM
+              NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+              NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' Fetching NEWS groups from remote node.''
+     &			,''  This will take several minutes.'')')
+		 WRITE (6,'('' This is the only time this will have''
+     &			,'' to be done.'')')
+	         CALL CLOSE_BULLFOLDER
+		 FOLDER1_SAVE = FOLDER1
+		 CALL NEWS_LIST
+	         CALL OPEN_BULLFOLDER_SHARED
+		 FOLDER1 = FOLDER1_SAVE
+	      ELSE IF (NEWS_F1_COUNT.GT.LAST_NEWS_READ(1,FOLDER_MAX).AND.
+     &		       OUTPUT.AND.NEWS_F1_COUNT.GT.LAST_NEWS_GROUP) THEN
+		 IF (LAST_NEWS_READ(1,FOLDER_MAX).GT.1000) THEN
+		    FOLDER1_SAVE = FOLDER1
+	            FOLDER1_NUMBER = LAST_NEWS_READ(1,FOLDER_MAX)
+	            IER = 2
+		    DO WHILE (IER.EQ.2)
+		       CALL READ_FOLDER_FILE_KEYNUM_GT_TEMP
+     &		          (FOLDER1_NUMBER,IER)
+		       IF (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10)) IER = 2
+	            END DO
+		    FOLDER1 = FOLDER1_SAVE
+		 END IF
+		 IF (LAST_NEWS_READ(1,FOLDER_MAX).GT.1000
+     &			.AND.IER.EQ.0) THEN
+		    WRITE (6,'('' Type NEWS/NEWGROUP to see recently'',
+     &			       '' added news groups.'')')
+		 ELSE
+		    LAST_NEWS_READ(1,FOLDER_MAX) = NEWS_F1_COUNT
+		 END IF
+		 LAST_NEWS_GROUP = NEWS_F1_COUNT
+		 FOLDER1_SAVE = FOLDER1
+	         CALL STR$UPCASE(FOLDER1,FOLDER1)
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &				(FOLDER1(:INDEX(FOLDER1,'.')),IER)
+	         IF (IER.EQ.0) THEN
+		    IF (NEWS_F1_EXPIRE.GT.0) 
+     &		       NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+		    IF (NEWS_F1_EXPIRE_LIMIT.NE.0) 
+     &		       NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	         END IF
+	         FOLDER1 = FOLDER1_SAVE
+	      END IF
+	      CALL LOWERCASE(FOLDER1)
+	   ELSE
+	      CALL OPEN_BULLFOLDER_SHARED		! Go find folder
+	   END IF
+
+	   IF ((OUTPUT.AND.(FOLDER_NUMBER.NE.0.OR.FOLDER1.NE.'GENERAL'))
+     &		.OR.FOLDER_NUMBER.LE.-1) THEN
+	      REMOTE_TEST = INDEX(FOLDER1,'::')
+	      IF (REMOTE_TEST.GT.0) THEN
+	         FOLDER1_BBOARD = '::'//FOLDER1(:REMOTE_TEST-1)
+	         FOLDER1 = FOLDER1(REMOTE_TEST+2:TRIM(FOLDER1))
+	         FOLDER1_NUMBER = -1
+	         IER = 0
+	      ELSE IF (INCMD(:2).EQ.'SE') THEN
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &				(FOLDER1(:TRIM(FOLDER1)),IER)
+	      ELSE
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	      END IF
+	   ELSE
+	      FOLDER1_NUMBER = FOLDER_NUMBER
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(FOLDER_NUMBER,IER)
+	   END IF
+
+	   IF (REMOTE_TEST.EQ.0.AND.IER.EQ.0) THEN
+	      IF (BTEST(FOLDER1_FLAG,29)) THEN		! Error in folder flag!!
+	         FOLDER1_FLAG = FOLDER1_FLAG.AND.3
+	         F1_EXPIRE_LIMIT = 0
+	         CALL REWRITE_FOLDER_FILE_TEMP(IER1)
+	      END IF
+	   END IF
+
+	   CALL CLOSE_BULLFOLDER
+
+	   IF (NEWS.AND.BTEST(FOLDER1_FLAG,8).AND.IER.EQ.0) THEN
+	      REMOTE_SET_NEW = 4
+	      CALL SYS_BINTIM('-',EX_BTIM)
+	   END IF
+	END IF
+
+	IF (BTEST(FOLDER1_FLAG,9)) THEN
+	   IF (OUTPUT) THEN
+	       WRITE(6,'('' This news group has been disabled.'')')
+	   END IF
+	   IER = 2
+	   RETURN
+	END IF
+
+	IF ((IER.EQ.0.OR.NEWS).AND.REMOTE_SET_NEW.NE.4.AND.
+     &		FOLDER1_BBOARD(:2).EQ.'::') THEN
+	   IF (FOLDER_NUMBER.EQ.-2) RETURN	! Don't allow
+	   IF (IER.NE.0) FOLDER1_DESCRIP = FOLDER1_NAME
+	   LOCAL_FOLDER1_FLAG = FOLDER1_FLAG
+	   LOCAL_FOLDER1_DESCRIP = FOLDER1_DESCRIP
+	   CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER1)
+	   IF (IER1.NE.0) THEN
+	      IF (OUTPUT) THEN
+	         WRITE (6,'('' ERROR: Unable to select the folder.'')')
+		 IF (.NOT.NEWS) THEN
+		    LENB = TRIM(FOLDER1_BBOARD)
+		    IF (FOLDER1_BBOARD(LENB:LENB).EQ.'*') LENB = LENB - 1
+	            WRITE (6,'('' Cannot connect to node '',A,''.'')')
+     &		        FOLDER1_BBOARD(3:LENB)
+		 ELSE IF (.NOT.IER1) THEN
+	            WRITE (6,'('' Cannot connect to remote NEWS node.'')')
+	         END IF
+	      END IF
+	      RETURN
+	   END IF
+	   IF (REMOTE_TEST.GT.0) THEN	! Folder specified with "::"
+	      FOLDER1 = FOLDER1_BBOARD(3:TRIM(FOLDER1_BBOARD))//'::'//
+     &			FOLDER1
+	      FOLDER1_NUMBER = -1
+	      REMOTE_SET_NEW = 1
+	   ELSE IF (NEWS) THEN
+	      REMOTE_SET_NEW = 3
+	      CALL OPEN_BULLNEWS_SHARED	! Update local folder information
+	      IF (IER.NE.0) CALL NEWS_NEW_FOLDER
+              CALL READ_FOLDER_FILE_KEYNAME(FOLDER1,IER)
+	      IF ((F1_START.NE.F_START.OR.F1_NBULL.NE.F_NBULL).AND.
+     &		  (F1_START.GT.0.OR.F_START.LE.F_NBULL)) THEN
+	         IF (F1_NBULL.NE.F_NBULL) CALL SYS_BINTIM('-',F_NEWEST_BTIM)
+	         F_COUNT = F1_COUNT
+		 IF (F1_START.GT.0) THEN
+		    IF (F1_NBULL.LT.F_NBULL) THEN
+		       CALL NEWS_GET_NEWEST_MESSAGE(IER)
+		       IF (IER-1.GE.F1_NBULL) THEN 
+			  CALL NEWS_UPDATE_NEWEST_MESSAGE(F_NBULL)
+		       END IF
+		    ELSE
+	               F_NBULL = F1_NBULL
+		    END IF
+	            F_START = F1_START
+		 ELSE
+		    F_START = F_NBULL + 1
+		 END IF
+	         CALL REWRITE_FOLDER_FILE(IER)
+	      END IF
+	      CALL CLOSE_BULLFOLDER
+	   ELSE				! True remote folder
+	      FOLDER1_DESCRIP = LOCAL_FOLDER1_DESCRIP	! Use local description
+	      IF (BTEST(FOLDER1_FLAG,0)) THEN	! If remote folder is protected
+		 LOCAL_FOLDER1_FLAG = IBSET(LOCAL_FOLDER1_FLAG,0)
+	      END IF
+	      FOLDER1_FLAG = LOCAL_FOLDER1_FLAG		! Use local flag info
+	      REMOTE_SET_NEW = 1
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN				! Folder found
+	   FLAG1_ACCESS = .TRUE.
+	   CALL SET_FOLDER_FILE(1)
+	   IF (BTEST(FOLDER1_FLAG,0)) THEN		! Folder protected?
+	      IF (NEWS) THEN
+		 CALL CHKACL(NEWS_ACCESS(FOLDER1_DESCRIP),IER)
+	      ELSE
+	         CALL CHKACL
+     &		 (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',IER)
+	      END IF
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.USERNAME
+     &		  .NE.FOLDER1_OWNER.AND.IER) THEN
+	         IF (NEWS) THEN
+	            CALL CHECK_ACCESS
+     &		     (NEWS_ACCESS(FOLDER1_DESCRIP),
+     &		     USERNAME,READ_ACCESS,WRITE_ACCESS)
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		     USERNAME,READ_ACCESS,WRITE_ACCESS)
+	         END IF
+	         IF (SETPRV_PRIV().AND.READIT.EQ.0) THEN
+		    IF (.NOT.READ_ACCESS) FLAG1_ACCESS = .FALSE.
+	            READ_ACCESS = 1
+		    WRITE_ACCESS = 1
+	         END IF
+	         IF (.NOT.READ_ACCESS.AND..NOT.WRITE_ACCESS) THEN
+		  IF (OUTPUT.AND.NEWS) THEN
+	           WRITE(6,'('' You are not allowed to access news group.'')')
+		  ELSE IF (NEWS) THEN
+		   IF (NEWS_FIND_SUBSCRIBE().LE.FOLDER_MAX-1) THEN
+		      CALL NEWS_SET_USER_FLAG(0,0,0)
+		   END IF
+		  ELSE IF (OUTPUT) THEN
+	           WRITE(6,'('' You are not allowed to access folder.'')')
+	           WRITE(6,'('' See '',A,'' if you wish to access folder.'')')
+     &			FOLDER1_OWNER(:TRIM(FOLDER1_OWNER))
+		  ELSE IF (TEST2(BRIEF_FLAG,FOLDER1_NUMBER).OR.
+     &			 TEST2(SET_FLAG,FOLDER1_NUMBER)) THEN
+		   CALL OPEN_BULLUSER_SHARED
+		   CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+		   CALL CLR2(BRIEF_FLAG,FOLDER1_NUMBER)
+		   CALL CLR2(SET_FLAG,FOLDER1_NUMBER)
+		   IF (IER.EQ.0) REWRITE (4) USER_ENTRY
+		   CALL CLOSE_BULLUSER
+		  END IF
+		  IER = 0
+		  RETURN
+	         END IF
+	      ELSE IF (BTEST(FOLDER1_FLAG,0).AND.(.NOT.IER.OR.
+     &		  (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND..NOT.NEWS))
+     &		  .AND.(FOLDER1_BBOARD(:2).NE.'::'.OR.NEWS)) THEN
+	         IF (NEWS) THEN
+	            CALL OPEN_BULLNEWS_SHARED
+	         ELSE
+	            CALL OPEN_BULLFOLDER
+	         END IF
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER1)
+		 FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+	         CALL REWRITE_FOLDER_FILE_TEMP(IER1) 
+		 CALL CLOSE_BULLFOLDER
+	      ELSE IF (FOLDER1_BBOARD(:2).EQ.'::') THEN
+	         IER = SS$_ACLEMPTY.OR.SS$_NORMAL
+	      END IF
+	   ELSE					! Folder not protected
+	      IER = SS$_ACLEMPTY.OR.SS$_NORMAL	! Indicate folder selected
+	   END IF
+
+	   IF (REMOTE_SET_NEW.NE.1.AND.REMOTE_SET.EQ.1) 
+     &					CLOSE(UNIT=REMOTE_UNIT)
+
+	   REMOTE_SET = REMOTE_SET_NEW 
+
+	   IF (IER) THEN
+	      FLAG_ACCESS = FLAG1_ACCESS	! Can set flags?
+
+	      FOLDER_COM = FOLDER1_COM		! Folder successfully set so
+	      FOLDER_FILE = FOLDER1_FILE	! update folder parameters
+
+	      IF (FOLDER_NUMBER.NE.0) THEN
+		 FOLDER_SET = .TRUE.
+	      ELSE
+		 FOLDER_SET = .FALSE.
+	      END IF
+
+	      IF (REMOTE_SET.LT.3) THEN
+		 FOLDER_NAME = FOLDER
+	         HEADER = .NOT.BTEST(FOLDER_FLAG,4)
+	      ELSE
+		 IF (COMMAND.AND.INCMD(:3).NE.'REP'.AND.
+     &		     INCMD(:3).NE.'DEL') HEADER = .FALSE.
+		 FOLDER_NAME = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	         IF (REMOTE_SET.EQ.4) NEWS_FOLDER_COM = NEWS_FOLDER1_COM
+	      END IF
+
+	      IF (REMOTE_SET.EQ.1.AND.FOLDER_NUMBER.GE.0) THEN
+	         CALL OPEN_BULLFOLDER	! Update local folder information
+                 CALL READ_FOLDER_FILE_KEYNAME(FOLDER1,IER1)
+	         OLD_NEWEST_BTIM(1) = F_NEWEST_BTIM(1)
+      	         OLD_NEWEST_BTIM(2) = F_NEWEST_BTIM(2)
+	         FOLDER_COM = FOLDER1_COM
+	         CALL REWRITE_FOLDER_FILE(IER1)
+	         CALL CLOSE_BULLFOLDER
+	         DIFF = COMPARE_BTIM(OLD_NEWEST_BTIM,F_NEWEST_BTIM)
+	         IF (DIFF.LT.0.AND.IER1.EQ.0) THEN
+	            CALL READ_NOTIFY
+	            IF (TEST2(NOTIFY_REMOTE,FOLDER_NUMBER)) THEN
+		       CALL NOTIFY_REMOTE_USERS(OLD_NEWEST_BTIM)
+	            END IF
+	         END IF
+	      END IF
+
+	      IF (REMOTE_SET.EQ.0.AND..NOT.BTEST(FOLDER_FLAG,10)
+     &		   .AND..NOT.BTEST(FOLDER_FLAG,11).AND.WRITE_ACCESS) THEN
+	         SLIST = INDEX(FOLDER_DESCRIP,'<')
+                 IF (OUTPUT.AND.INCMD(:3).NE.'DIR') THEN
+                    IF (NEWS_FEED()) THEN
+                       WRITE (6,'('' Use the POST command to send a '',
+     &                 ''message to this folder''''s news group.'')')
+		    ELSE IF (SLIST.GT.0) THEN
+                       WRITE (6,'('' Use the POST command to send a '',
+     &                 ''message to this folder''''s mailing list.'')')
+                    END IF
+                 END IF
+	      END IF
+
+	      IF (OUTPUT.AND.INCMD(:3).NE.'DIR') THEN
+		 WRITE (6,'('' Folder has been set to '',A)') 
+     &		    FOLDER_NAME(:TRIM(FOLDER_NAME))//'.'
+	      END IF
+
+	      IF (OUTPUT) THEN
+		 IF (REMOTE_SET.EQ.3) THEN
+		    BULL_POINT = F_START - 1
+		    FSTATUS(:1) = 
+     &			FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,' ')+1:)
+		    IF (STREQ(FSTATUS(:1),'X')) THEN
+		       WRITE (6,'('' WARNING: The local news server has'',
+     &				  '' deactivated this group.'')')
+		    ELSE IF (STREQ(FSTATUS(:1),'=')) THEN
+		       WRITE (6,'('' NOTE: This group is no longer'',
+     &				  '' active.  It has been replaced by:'')')
+		       WRITE (6,'(1X,A)') FOLDER_DESCRIP(
+     &				       INDEX(FOLDER_DESCRIP,'=')+1:)
+		    END IF
+		 ELSE IF (REMOTE_SET.EQ.4) THEN
+		    BULL_POINT = F_START - 1 
+		 ELSE
+		    BULL_POINT = 0	! Reset pointer to first bulletin
+	         END IF
+	      ELSE IF (REMOTE_SET.EQ.3.OR.REMOTE_SET.EQ.4) THEN
+		 BULL_POINT = F_START - 1
+	      END IF
+
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.USERNAME
+     &		  .NE.FOLDER_OWNER) THEN
+	         IF (.NOT.WRITE_ACCESS) THEN
+		   IF (OUTPUT.AND.INCMD(:3).NE.'DIR'.AND.SLIST.EQ.0) THEN
+		    WRITE (6,'('' Folder only accessible for reading.'')')
+		   END IF
+		   READ_ONLY = .TRUE.
+		 ELSE
+		   READ_ONLY = .FALSE.
+		 END IF
+	      ELSE
+		 READ_ONLY = .FALSE.
+	      END IF
+
+	      IF (FOLDER_NUMBER.GT.0.AND.REMOTE_SET.LT.3) THEN
+		IF (TEST_BULLCP().GT.0.OR.REMOTE_SET) THEN
+		 CALL SET2(FIRST_TIME,FOLDER_NUMBER)
+		ELSE IF (.NOT.TEST2(FIRST_TIME,FOLDER_NUMBER)) THEN
+	       			! If first select, look for expired messages.
+		 CALL OPEN_BULLDIR
+		 CALL READDIR(0,IER)	! Get header info from BULLDIR.DAT
+	 	 IF (IER.EQ.1) THEN		! Is header present?
+	   	    IER = COMPARE_DATE(NEWEST_EXDATE,' ') ! Yes. Any expired?
+		    IF (SHUTDOWN.GT.0.AND.NODE_AREA.GT.0.AND.
+     &			(FOLDER_NUMBER.EQ.0.OR.BTEST(FOLDER_FLAG,2))
+     &			.AND.TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+						! Do shutdown bulletins exist?
+		       SHUTDOWN = 0
+		       IER1 = -1
+		    ELSE
+		       IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+			  CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+		       END IF
+	               IER1 = 1
+		    END IF
+	 	    IF (IER.LE.0.OR.IER.GT.20*356.OR.IER1.LE.0) THEN
+		       CALL UPDATE	! Need to update
+		    END IF
+		 ELSE
+		    NBULL = 0
+		 END IF
+		 CALL CLOSE_BULLDIR
+		 CALL SET2(FIRST_TIME,FOLDER_NUMBER)
+	        END IF
+	      END IF
+
+	      IF (OUTPUT) THEN
+		 IF (CLI$PRESENT('MARKED')) THEN
+		    READ_TAG = 1 + IBSET(0,1)
+		    BULL_PARAMETER = 'MARKED'
+		 ELSE IF (CLI$PRESENT('SEEN')) THEN
+		    READ_TAG = 1 + IBSET(0,2)
+		    BULL_PARAMETER = 'SEEN'
+	         ELSE IF (CLI$PRESENT('UNMARKED').OR.CLI$PRESENT
+     &		       ('MARKED').EQ.%LOC(CLI$_NEGATED)) THEN
+		    READ_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+		    BULL_PARAMETER = 'UNMARKED'
+	         ELSE IF (CLI$PRESENT('UNSEEN').OR.CLI$PRESENT
+     &		       ('SEEN').EQ.%LOC(CLI$_NEGATED)) THEN
+		    READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+		    BULL_PARAMETER = 'UNSEEN'
+		 ELSE
+		    READ_TAG = IBSET(0,1) + IBSET(0,2)
+		 END IF
+	         IF (READ_TAG) THEN
+	            IF (FOLDER_NUMBER.GE.0) THEN
+		       CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,BULL_POINT)
+		    ELSE
+		       WRITE (6,'('' ERROR: invalid qualifier'',
+     &			          '' with remote folder.'')')
+		       READ_TAG = IBSET(0,1) + IBSET(0,2)
+		    END IF
+	         END IF
+	         IF (READ_TAG.AND.INCMD(:3).NE.'DIR') THEN
+		    IF (IER.EQ.0) THEN
+		       WRITE(6,'('' NOTE: Only '',A,'' messages'',
+     &			   '' will be shown.'')')
+     &			   BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+		    ELSE
+		       WRITE(6,'('' WARNING: No '',A,
+     &			   '' messages found.'')')
+     &		 	   BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+		    END IF
+	         END IF
+	      END IF
+
+	      IF (REMOTE_SET.GE.3.AND.OUTPUT.AND..NOT.READ_TAG) THEN
+		 CALL NEWS_GET_NEWEST_MESSAGE(IER)
+		 IF (IER.GT.0.AND.IER.LE.F_NBULL) THEN
+		    BULL_POINT = IER - 1
+	            WRITE(6,'('' Type READ to read new messages.'')')
+		 END IF
+	      ELSE IF (FOLDER_NUMBER.NE.0.AND..NOT.READ_TAG.AND.
+     &		  				REMOTE_SET.LT.3) THEN
+	        IF (OUTPUT.AND.INCMD(:3).NE.'DIR') THEN
+	         DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+	         IF (DIFF.LT.0.AND.F_NBULL.GT.0) THEN 	! If new unread messages
+		  CALL FIND_NEWEST_BULL			! See if we can find it
+		  IF (BULL_POINT.NE.-1) THEN
+	     	    WRITE(6,'('' Type READ to read new messages.'')')
+		    NEW_COUNT = F_NBULL - BULL_POINT
+		    DIG = 0
+		    DO WHILE (NEW_COUNT.GT.0)
+		      NEW_COUNT = NEW_COUNT / 10
+		      DIG = DIG + 1
+		    END DO
+		    WRITE(6,'('' There are '',I<DIG>,'' new messages.'')')
+     &			F_NBULL - BULL_POINT	! Alert user if new bulletins
+		  ELSE
+		    CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &			       F_NEWEST_BTIM)
+		    BULL_POINT = 0
+		  END IF
+		 END IF
+		END IF
+	      END IF
+	      IER = 1
+	      IF (TEST_BULLCP().NE.2) CALL CHECK_CUSTOM
+	      IF (BTEST(BULL_USER_CUSTOM,2)) HEADER = .TRUE.
+	   ELSE IF (OUTPUT) THEN
+	      WRITE (6,'('' Cannot access specified folder.'')')
+	      CALL SYS_GETMSG(IER)
+	   END IF
+	ELSE						! Folder not found
+	   IF (OUTPUT) WRITE (6,'('' ERROR: Folder does not exist.'')')
+	   IER = 0
+	END IF
+
+	LAST_FOLDER_NUMBER = FOLDER_NUMBER 
+
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE UPDATE_FOLDER
+C
+C  SUBROUTINE UPDATE_FOLDER
+C
+C  FUNCTION: Updates folder info due to new message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	IF (FOLDER_NUMBER.LT.0) RETURN
+
+	CALL OPEN_BULLFOLDER_SHARED			! Open folder file
+
+	CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,F_NEWEST_BTIM)
+
+	F_NBULL = NBULL
+
+	IF (FOLDER_NUMBER.EQ.0) FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+
+	IF (.NOT.BTEST(SYSTEM,0)) THEN 	! Is non-system message?
+	   F_NEWEST_NOSYS_BTIM(1) = F_NEWEST_BTIM(1) ! If so, update latest
+	   F_NEWEST_NOSYS_BTIM(2) = F_NEWEST_BTIM(2) ! system time.
+	END IF
+
+	CALL REWRITE_FOLDER_FILE(IER)
+
+	CALL CLOSE_BULLFOLDER
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SHOW_FOLDER
+C
+C  SUBROUTINE SHOW_FOLDER
+C
+C  FUNCTION: Shows the information on any folder.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /BULL_PERM/ SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	DIMENSION SET_PERM_FLAG(FLONG)
+	DIMENSION BRIEF_PERM_FLAG(FLONG)
+	DIMENSION NOTIFY_PERM_FLAG(FLONG)
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	EXTERNAL CLI$_ABSENT,BULLETIN_SUBCOMMANDS
+
+	IF (INDEX(INCMD,'/A').GT.0.OR.INDEX(INCMD,'/a').GT.0) THEN
+	   WRITE (6,'('' ERROR: /ALL is invalid qualifier.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$GET_VALUE('SHOW_FOLDER',FOLDER1).EQ.%LOC(CLI$_ABSENT))
+     &	   THEN
+	   FOLDER1 = FOLDER
+	   IF (INDEX(FOLDER1,'.').GT.0) CALL LOWERCASE(FOLDER1)
+	END IF
+
+	IF (INDEX(FOLDER1,'::').NE.0) THEN
+ 	   WRITE (6,'('' ERROR: invalid command for remote folder.'')')
+	   RETURN
+	END IF
+
+	IF (TEST_NEWS(FOLDER1)) THEN              
+	   INCMD = 'SET NEWS '
+	   IF (CLI$PRESENT('FULL')) INCMD = 'SET NEWS/FULL '
+	   IF (CLI$PRESENT('SHOW_FOLDER')) INCMD = 'SET NEWS '//FOLDER1
+           CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	   CALL SHOW_NEWS
+	   RETURN
+        END IF
+
+	CALL OPEN_BULLFOLDER_SHARED
+
+	CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Specified folder was not found.'')')
+	   CALL CLOSE_BULLFOLDER
+	   RETURN
+	ELSE IF (FOLDER.EQ.FOLDER1) THEN
+	   WRITE (6,1000) FOLDER1,FOLDER1_OWNER,
+     &			FOLDER1_DESCRIP(:TRIM(FOLDER1_DESCRIP))
+	ELSE
+	   WRITE (6,1010) FOLDER1,FOLDER1_OWNER,
+     &			FOLDER1_DESCRIP(:TRIM(FOLDER1_DESCRIP))
+	END IF
+
+	IF (CLI$PRESENT('FULL')) THEN
+	   CALL SET_FOLDER_FILE(1)
+	   CALL CHKACL
+     &		 (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',IER)
+	   IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL).OR.(.NOT.IER)) THEN
+	      IF (FOLDER1_BBOARD(:2).EQ.'::'.AND.	! Is folder remote
+     &		BTEST(FOLDER1_FLAG,0)) THEN		! and private?
+	         WRITE (6,'('' Access is limited.'')')
+	      END IF
+	   ELSE
+	      IF (SETPRV_PRIV()) THEN
+	         READ_ACCESS = 1
+		 WRITE_ACCESS = 1
+	      ELSE
+	        CALL CHECK_ACCESS
+     &		  (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		   USERNAME,READ_ACCESS,WRITE_ACCESS)
+	      END IF
+	      IF (WRITE_ACCESS)
+     &	      CALL SHOWACL(FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL')
+	   END IF
+	   IF (FOLDER_ACCESS(USERNAME,FOLDER1_FLAG,FOLDER1_OWNER)) THEN
+	      IF (FOLDER1_BBOARD(:2).EQ.'::') THEN
+		 FLEN = TRIM(FOLDER1_BBOARD)
+		 IF (INDEX(FOLDER1_BBOARD,'*').EQ.0) THEN
+		    WRITE (6,'('' Folder is located on node '',
+     &		     A,''.'')') FOLDER1_BBOARD(3:FLEN)
+		 ELSE
+		    CALL SET_FOLDER_FILE(1)
+		    FOLDER_FILE = FOLDER1_FILE
+		    REMOTE_SET_SAVE = REMOTE_SET
+		    REMOTE_SET = .FALSE.
+		    CALL OPEN_BULLDIR
+		    CALL READDIR(0,IER)
+		    CALL CLOSE_BULLDIR
+		    CALL SET_FOLDER_FILE(0)
+		    REMOTE_SET = REMOTE_SET_SAVE
+		    WRITE (6,'('' Folder is located on node '',
+     &		       A,''. Remote folder name is '',A,''.'')') 
+     &		       FOLDER1_BBOARD(3:FLEN-1),
+     &		       BULLDIR_HEADER(13:TRIM(BULLDIR_HEADER))
+		 END IF
+	      ELSE IF (FOLDER1_BBOARD(:4).NE.'NONE') THEN
+		 FLEN = TRIM(FOLDER1_BBOARD)
+		 IF (FLEN.GT.0) THEN
+ 	          WRITE (6,'('' BBOARD for folder is '',A<FLEN>,''.'')')
+     &		 	FOLDER1_BBOARD(:FLEN)
+		 END IF
+		 IF ((USERB1.EQ.0.AND.GROUPB1.EQ.0).OR.BTEST(USERB1,31)) THEN
+ 		  WRITE (6,'('' BBOARD was specified with /SPECIAL.'')')
+		  IF (BTEST(GROUPB1,31)) THEN
+		   WRITE (6,'('' BBOARD was specified with /VMSMAIL.'')')
+		  END IF
+		 END IF
+	      ELSE
+	         WRITE (6,'('' No BBOARD has been defined.'')')
+	      END IF
+	      IF (FOLDER1_BBEXPIRE.GT.0) THEN
+		 WRITE (6,'('' Default expiration is '',I3,'' days.'')')
+     &			FOLDER1_BBEXPIRE
+	      ELSE IF (FOLDER1_BBEXPIRE.EQ.-1) THEN
+		 WRITE (6,'('' Default expiration is permanent.'')')
+	      ELSE
+		 WRITE (6,'('' No default expiration set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,2)) THEN
+		 WRITE (6,'('' SYSTEM has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,1)) THEN
+		 WRITE (6,'('' DUMP has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,3)) THEN
+		 WRITE (6,'('' NOPROMPT_EXPIRE has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,4)) THEN
+		 WRITE (6,'('' STRIP has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,5)) THEN
+		 WRITE (6,'('' DIGEST has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,7)) THEN
+		 WRITE (6,'('' ALWAYS has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,10)) THEN
+		 WRITE (6,'('' POST_ONLY has been set.'')')
+	      ELSE IF (BTEST(FOLDER1_FLAG,11)) THEN
+		 WRITE (6,'('' ADD_ONLY has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,12)) THEN
+		 WRITE (6,'('' COMPRESS has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,14)) THEN
+		 WRITE (6,'('' ANONYMOUS has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,15)) THEN
+		 WRITE (6,'('' GATEWAY has been set.'')')
+	      END IF
+	      IF (F1_EXPIRE_LIMIT.GT.0) THEN
+		 WRITE (6,'('' EXPIRATION limit is '',I3,'' days.'')')
+     &			F1_EXPIRE_LIMIT
+	      END IF
+	      CALL OPEN_BULLUSER_SHARED
+	      CALL READ_USER_FILE_HEADER(IER)
+	      CALL READ_PERM
+	      PERM = .FALSE.
+	      IF (TEST2(SET_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	       IF (TEST2(BRIEF_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	        IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is BRIEF, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is BRIEF.'')')
+		END IF
+	       ELSE
+	        IF (TEST2(SET_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER)) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is READNEW, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is READNEW.'')')
+		END IF
+	       END IF
+	      ELSE
+	       IF (TEST2(BRIEF_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	        IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is SHOWNEW, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is SHOWNEW.'')')
+		END IF
+	       END IF
+	      END IF
+	      IF (.NOT.PERM) THEN
+	        IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		   WRITE (6,'('' BRIEF is the permanent setting.'')')
+	        ELSE IF (TEST2(SET_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		   WRITE (6,'('' READNEW is the permanent setting.'')')
+	        ELSE IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		   WRITE (6,'('' SHOWNEW is the permanent setting.'')')
+	        END IF
+	      END IF
+	      IF (TEST2(NOTIFY_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	        IF (TEST2(NOTIFY_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		 WRITE (6,'('' Default is NOTIFY, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is NOTIFY.'')')
+		END IF
+	      ELSE
+		 WRITE (6,'('' Default is NONOTIFY.'')')
+	      END IF
+	      CALL CLOSE_BULLUSER
+	   END IF
+	   IF (NEWS_FEED()) THEN
+	      WRITE (6,'('' Last message fed by news group was: '',I)') F_LAST
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLFOLDER
+
+	RETURN
+
+1000	FORMAT(' Current folder: ',A44,' Owner: ',A12,/,
+     &		' Description: ',A)
+1010	FORMAT(' Folder name is: ',A44,' Owner: ',A12,/,
+     &		' Description: ',A)
+	END
+
+
+	SUBROUTINE DIRECTORY_FOLDERS(FOLDER_COUNT)
+C
+C  SUBROUTINE DIRECTORY_FOLDERS
+C
+C  FUNCTION: Display all FOLDER entries.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	DATA SCRATCH_D1/0/
+
+	CHARACTER FOLDER_MATCH*80,DATETIME*20,FSTATUS1*4,NEWS_ACCESS*132 
+
+	INTEGER*2 MLEN,FLEN
+
+	OLD_BUFFER = ' '
+
+	IF (CLI$PRESENT('NEWS')) THEN
+	   IF (SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) THEN
+	      CALL OPEN_BULLNEWS_SHARED
+	   ELSE
+	      WRITE (6,'('' ERROR: NEWS connection is not present.'')')
+	      RETURN
+	   END IF
+	ELSE
+	   CALL OPEN_BULLFOLDER_SHARED		! Get folder file
+	END IF
+
+	IF (FOLDER_COUNT.EQ.0) THEN
+	   SUBSCRIBE = .FALSE.
+	   ACTIVE = .FALSE. 
+	   STORED = .FALSE. 
+	   CLASS = .FALSE.
+	   NEW = .FALSE.
+	   PERM = .FALSE.
+	   DEFA = .FALSE.
+	   FOLDER_COUNT = 1			! Init folder number counter
+	   NLINE = 1
+	   START = .FALSE.
+	   IF (.NOT.CLI$PRESENT('NEWS')) THEN
+	      NEWS = .FALSE.
+	      IF (CLI$PRESENT('DESCRIBE')) THEN
+	         NLINE = 2	! Include folder descriptor if /DESCRIBE
+	      END IF
+	   ELSE
+	      NEWS = .TRUE.
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP('a',IER)
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' Fetching NEWS groups from remote node.''
+     &			,''  This will take several minutes.'')')
+		 WRITE (6,'('' This is the only time this will have''
+     &			,'' to be done.'')')
+	         CALL CLOSE_BULLFOLDER
+		 CALL NEWS_LIST
+	         CALL OPEN_BULLNEWS_SHARED
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP('a',IER)
+	      END IF
+	      COUNT = CLI$PRESENT('COUNT')
+	      IF (COUNT) TOTAL_COUNT = 0
+	      STORED = CLI$PRESENT('STORED')
+	      SUBSCRIBE = CLI$PRESENT('SUBSCRIBE')
+	      NEW = CLI$PRESENT('NEWGROUPS')
+	      CLASS = CLI$PRESENT('CLASS')
+	      PERM = CLI$PRESENT('PERMANENT')
+	      DEFA =  CLI$PRESENT('DEFAULT')
+	      IF (CLASS) THEN
+	         CALL CLOSE_BULLFOLDER
+	         CALL OPEN_BULLNEWS_SHARED
+	      END IF
+	      IF (NEW) THEN
+		 NEW_NEWS = MAX(LAST_NEWS_READ(1,FOLDER_MAX),1000)
+	      ELSE IF (SUBSCRIBE) THEN
+		 CALL NEWS_GET_SUBSCRIBE(0,F1_COUNT)
+		 SUBNUM = 1
+	      ELSE IF (PERM) THEN
+	      	 CALL OPEN_BULLINF_SHARED
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,KEY='*PERM',IOSTAT=IER) TEMP_USER,INF_REC
+		 END DO
+		 IF (IER.NE.0) THEN
+	            DO I=1,FOLDER_MAX
+	               INF_REC(1,I) = 0
+	               INF_REC(2,I) = 0
+	            END DO
+	         END IF
+		 CALL CLOSE_BULLINF
+		 INUM = 1
+	      ELSE IF (DEFA) THEN
+	      	 CALL OPEN_BULLINF_SHARED
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,KEY='*DEFAULT',IOSTAT=IER) TEMP_USER,INF_REC
+		 END DO
+		 IF (IER.NE.0) THEN
+	            DO I=1,FOLDER_MAX
+	               INF_REC(1,I) = 0
+	               INF_REC(2,I) = 0
+	            END DO
+	         END IF
+		 CALL CLOSE_BULLINF
+		 INUM = 1
+	      ELSE
+	         ACTIVE = .NOT.CLI$PRESENT('ALL')
+	      END IF
+	   END IF
+	   IF (CLI$GET_VALUE('START',FOLDER1,FLEN)) THEN
+	      IF (NEWS) CALL LOWERCASE(FOLDER1)
+	      CALL READ_FOLDER_FILE_KEYNAMEGE_TEMP(FOLDER1(:FLEN),IER)
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' There are no folders.'')')
+	         CALL CLOSE_BULLFOLDER
+		 FOLDER_COUNT = -1
+		 RETURN
+	      ELSE
+		 START = .TRUE.
+	      END IF
+	   END IF
+	   MATCH = CLI$GET_VALUE('MATCH_FOLDER',FOLDER_MATCH,MLEN)
+	   IF (MATCH.AND.NEWS) CALL LOWERCASE(FOLDER_MATCH)
+	   IF (MATCH.AND.INDEX(FOLDER_MATCH,'*').EQ.0) THEN
+	      FOLDER_MATCH = '*'//FOLDER_MATCH(:MLEN)//'*'
+	      MLEN = MLEN + 2
+	   END IF
+	ELSE IF (NEWS.AND.COUNT.AND.TOTAL_COUNT.LT.0) THEN
+	   WRITE (6,'('' The total count is: '',I)') -TOTAL_COUNT
+	   TOTAL_COUNT = 0
+	   FOLDER_COUNT = -1
+	   RETURN
+	ELSE IF (SUBSCRIBE.AND.PAGING.AND.MORE) THEN
+	   SUBNUM = -2
+	ELSE
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	END IF
+
+C
+C  Folder listing is first buffered into temporary memory storage before
+C  being outputted to the terminal.  This is to be able to quickly close the
+C  folder file, and to avoid the possibility of the user holding the screen,
+C  and thus causing the folder file to stay open.  The temporary memory
+C  is structured as a linked-list queue, where SCRATCH_D1 points to the header
+C  of the queue.
+C
+	CALL INIT_QUEUE(SCRATCH_D1,FOLDER1_COM)
+	SCRATCH_D = SCRATCH_D1
+
+	CALL DECLARE_CTRLC_AST
+
+	NUM_FOLDER = 0
+	IER = 0
+	IER1 = 0
+	MORE = .FALSE.
+	NEWS_TEST = MATCH.OR.ACTIVE.OR.STORED
+	DO WHILE (IER.EQ.0.AND.IER1.EQ.0)
+	   IF (SUBSCRIBE) THEN
+	      IER = 1
+	      DO WHILE (SUBNUM.NE.0.AND.IER.NE.0)
+	         CALL NEWS_GET_SUBSCRIBE(SUBNUM,MSGNUM)
+		 IF (SUBNUM.NE.0) THEN
+	            CALL READ_FOLDER_FILE_KEYNUM_TEMP(SUBNUM,IER)
+		    IF (IER.NE.0) SUBNUM = -1
+		 END IF
+	      END DO
+	      IF (SUBNUM.EQ.0) IER = 1
+	   ELSE IF (PERM.OR.DEFA) THEN
+	      IER = 1
+	      DO WHILE (INUM.LE.FOLDER_MAX.AND.IER.NE.0)
+		 IF (INF_REC2(1,INUM).NE.0) THEN
+	            CALL READ_FOLDER_FILE_KEYNUM_TEMP
+     &				(ZEXT(INF_REC2(1,INUM)),IER)
+		 END IF
+		 INUM = INUM + 1
+	      END DO
+	   ELSE IF (START) THEN
+	      START = .FALSE.
+	   ELSE IF (NEW) THEN
+	      IER = 2
+	      DO WHILE (IER.EQ.2)
+	         CALL READ_FOLDER_FILE_KEYNUM_GT_TEMP(NEW_NEWS,IER)
+		 IF (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10)) THEN
+		    IER = 2
+	            NEW_NEWS = FOLDER1_NUMBER
+	         END IF
+	      END DO
+	      IF (IER.EQ.0) THEN
+	         NEW_NEWS = FOLDER1_NUMBER
+	      ELSE
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP('a',IER2)
+	         NEW_NEWS = NEWS_F1_COUNT
+	      END IF
+	   ELSE
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+	      IF (CLASS) CALL LOWERCASE(FOLDER1_DESCRIP)
+	      IF (CLASS) NEWS_TEST = .FALSE.
+	      IF (CLASS.AND.FOLDER1.EQ.'a') IER = 2
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF ((INDEX(FOLDER1_BBOARD,'::').EQ.0.OR.NEWS).AND.
+     &		  BTEST(FOLDER1_FLAG,0).AND..NOT.SETPRV_PRIV()) THEN
+		 CALL SET_FOLDER_FILE(1)
+	         IF (NEWS) THEN
+	            IF (OLD_BUFFER.NE.NEWS_ACCESS(FOLDER1_DESCRIP)) THEN
+	               OLD_BUFFER = NEWS_ACCESS(FOLDER1_DESCRIP)
+		       CALL CHKACL(OLD_BUFFER(:TRIM(OLD_BUFFER)),IER2)
+	   	       IF (IER2.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	                  CALL CHECK_ACCESS(OLD_BUFFER(:TRIM(OLD_BUFFER)),
+     &		           USERNAME,READ_ACCESS,-1)
+                       ELSE
+                          READ_ACCESS = 1
+                       END IF
+	            END IF
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		      USERNAME,READ_ACCESS,-1)
+	         END IF
+	      ELSE
+		 READ_ACCESS = 1
+	      END IF
+	      IF (READ_ACCESS) THEN
+	         J = INDEX(FOLDER1_DESCRIP,' ')
+	         IF (J.GT.0) THEN
+	            FSTATUS1(:1) = FOLDER1_DESCRIP(J+1:)
+		 ELSE
+	            FSTATUS1 = ' '
+		    J = TRIM(FOLDER1_DESCRIP) + 1
+	         END IF
+		 IF (.NOT.NEWS_TEST) THEN
+		    IF (NEWS.AND.CLASS) 
+     &			FOLDER1_DESCRIP = FOLDER1_DESCRIP(:J-2)
+	            NUM_FOLDER = NUM_FOLDER + 1
+	            CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,FOLDER1_COM)
+		 ELSE IF ((.NOT.ACTIVE.OR.(FSTATUS1(:1).NE.'x'.AND..NOT.
+     &			   BTEST(FOLDER1_FLAG,9))).AND.
+     &	                  (.NOT.STORED.OR.BTEST(FOLDER1_FLAG,8)).AND.
+     &			(.NOT.MATCH.OR.STR$MATCH_WILD(FOLDER1_DESCRIP
+     &		        (:J-1),FOLDER_MATCH(:MLEN)))) THEN
+		    GO TO 100
+	         END IF
+	      END IF
+	      IF (PAGING.AND.NUM_FOLDER*NLINE+2.GT.PAGE_LENGTH-4) THEN
+		 IER1 = 1
+		 MORE = .TRUE.
+	      END IF
+	   END IF
+	   IF (FLAG.EQ.1) IER1 = 1
+	END DO
+
+ 	IF (NEWS_TEST) NEWS_TEST = .FALSE.
+
+ 	IF (FLAG.EQ.1) THEN
+	   WRITE (6,'('' Listing aborted.'')')
+	   FOLDER_COUNT = -1
+	   CALL CANCEL_CTRLC_AST
+	   CALL CLOSE_BULLFOLDER
+	   RETURN
+	END IF
+
+	CALL CANCEL_CTRLC_AST
+	CALL CLOSE_BULLFOLDER			! We don't need file anymore
+
+	IF (NUM_FOLDER.EQ.0) THEN
+	   WRITE (6,'('' There are no folders.'')')
+	   FOLDER_COUNT = -1
+	   IF (NEW) LAST_NEWS_READ(1,FOLDER_MAX) = NEW_NEWS
+	   RETURN
+	END IF
+
+C
+C  Folder entries are now in queue.  Output queue entries to screen.
+C
+
+     	SCRATCH_D = SCRATCH_D1			! Init queue pointer to header
+
+100	CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+
+	IF (.NOT.NEWS) THEN
+	   WRITE (6,'(1X,''Folder'',22X,''Last message'',7X,''Messages'',
+     &		2X,''Owner'',/,1X,80(''-''))')
+	ELSE IF (COUNT) THEN
+	   WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,6X,
+     &		''First        Last  Count'',
+     &		/,1X,<PAGE_WIDTH>(''-''))')
+	ELSE IF (CLASS) THEN
+	   WRITE (6,'(1X,''Class'',/,1X,<PAGE_WIDTH>(''-''))')
+	ELSE IF (SUBSCRIBE) THEN
+	   WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,1X,
+     &		''First        Last   Last Read'',/,1X,<PAGE_WIDTH>(''-''))')
+	ELSE
+	   WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,''Status'',7X,
+     &		''First        Last'',/,1X,<PAGE_WIDTH>(''-''))')
+	END IF
+
+	IF (PAGING.AND.MORE) NUM_FOLDER = NUM_FOLDER - 1
+
+	I = 1
+	DO WHILE ((I.LE.NUM_FOLDER.OR.NEWS_TEST).AND.FLAG.NE.1.AND.
+     &		  FLAG.NE.100)
+	   IF (.NOT.NEWS_TEST) THEN
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,FOLDER1_COM)
+	      I = I + 1
+	   END IF
+	   IF (.NOT.NEWS) THEN
+	      DIFF = COMPARE_BTIM
+     &			(LAST_READ_BTIM(1,FOLDER1_NUMBER+1),F1_NEWEST_BTIM)
+	      IF (F1_NBULL.GT.0) THEN
+	         CALL SYS$ASCTIM(,DATETIME,F1_NEWEST_BTIM,)
+	      ELSE
+	         DATETIME = '      NONE'
+	      END IF
+	      IF (DIFF.GE.0.OR.F1_NBULL.EQ.0) THEN
+	         WRITE (6,1000) ' '//FOLDER1,DATETIME(:17),F1_NBULL,
+     &							FOLDER1_OWNER
+	      ELSE
+	         WRITE (6,1000) '*'//FOLDER1,DATETIME(:17),F1_NBULL,
+     &							FOLDER1_OWNER
+	      END IF
+	   ELSE
+	      IF (NEWS_TEST) UNLOCK 7
+	      FLEN = MIN(80,PAGE_WIDTH-80+49)
+	      IF (SUBSCRIBE) FLEN = MIN(81,PAGE_WIDTH-80+42)
+	      J = INDEX(FOLDER1_DESCRIP,' ')
+	      IF (J.GT.0) THEN
+	         FSTATUS1(:1) = FOLDER1_DESCRIP(J+1:)
+		 IF (FSTATUS1(:1).NE.'=') THEN
+                    FOLDER1_DESCRIP = FOLDER1_DESCRIP(:J-1)
+                 END IF
+	      ELSE
+	         FSTATUS1 = ' '
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,9)) FSTATUS1 = 'n'
+	      IF (COUNT) THEN
+		 TOTAL_COUNT = TOTAL_COUNT + F1_COUNT
+	         IF (F1_START.LE.F1_NBULL) THEN
+		    WRITE (6,1010) FOLDER1_DESCRIP(:FLEN),
+     &					 F1_START,F1_NBULL,F1_COUNT
+	         ELSE
+		    WRITE (6,1010) FOLDER1_DESCRIP(:FLEN),0,0,0
+		 END IF
+              ELSE IF (CLASS) THEN
+                 WRITE (6,1010) FOLDER1_DESCRIP(:FLEN)
+	      ELSE IF (F1_START.LE.F1_NBULL) THEN
+		 IF (SUBSCRIBE) THEN
+                    NEWS_FOLDER1_NUMBER = FOLDER1_NUMBER
+		    CALL NEWS_GET_NEWEST_MESSAGE1(NEWS_NEW)
+		    IF (NEWS_NEW-1.LT.F1_NBULL.AND.F1_NBULL.GT.0) THEN
+	               WRITE (6,1015) '* '//FOLDER1_DESCRIP(:FLEN-2),
+     &					F1_START,F1_NBULL,NEWS_NEW-1
+		    ELSE
+	               WRITE (6,1015) '  '//FOLDER1_DESCRIP(:FLEN-2),
+     &					F1_START,F1_NBULL,NEWS_NEW-1
+		    END IF
+		 ELSE
+		    WRITE (6,1005) FOLDER1_DESCRIP(:FLEN),
+     &					 FSTATUS1(:1),F1_START,F1_NBULL
+		 END IF
+	      ELSE IF (SUBSCRIBE) THEN
+	         WRITE (6,1015) ' '//FOLDER1_DESCRIP(:FLEN-1),0,0,0
+	      ELSE
+		 WRITE (6,1005) FOLDER1_DESCRIP(:FLEN),FSTATUS1(:1),0,0
+	      END IF
+	   END IF
+	   IF (NLINE.EQ.2) WRITE (6,'(1X,A)') FOLDER1_DESCRIP
+	   LAST_DISPLAY = FOLDER1_NUMBER
+	   IF (NEWS_TEST.AND.FLAG.NE.1) THEN
+	      NUM_FOLDER = NUM_FOLDER + 1
+	      IF (PAGING.AND.
+     &		  NUM_FOLDER*NLINE+2.GE.PAGE_LENGTH-4) MORE = .TRUE.
+	      CALL GET_NEXT_GROUP(MATCH,FOLDER_MATCH,MLEN,FOUND,STORED,
+     &				  FSTATUS1,IER,ACTIVE)
+	      MORE = MORE.AND.FOUND
+	      IF (MORE) THEN
+		 CALL READ_FOLDER_FILE_KEYNUM_TEMP(LAST_DISPLAY,IER)
+              END IF
+	      FOUND = FOUND.AND..NOT.MORE
+	      IF (.NOT.FOUND.AND.FLAG.NE.1) FLAG = 100
+	   END IF
+	END DO
+
+ 	IF (FLAG.EQ.1) THEN
+	   WRITE (6,'('' Listing aborted.'')')
+	   FOLDER_COUNT = -1
+	   CALL CANCEL_CTRLC_AST
+	   CALL CLOSE_BULLFOLDER
+	   RETURN
+	END IF
+
+	IF (NEWS_TEST) THEN
+	   CALL CANCEL_CTRLC_AST
+	   CALL CLOSE_BULLFOLDER
+	END IF
+
+	IF (IER.NE.0.AND..NOT.MORE) THEN	! Outputted all entries?
+	   IF (NEWS.AND.COUNT) THEN
+	      TOTAL_COUNT = -TOTAL_COUNT
+	   ELSE
+	      FOLDER_COUNT = -1			! Yes. Set counter to -1.
+	   END IF
+	   IF (NEW) LAST_NEWS_READ(1,FOLDER_MAX) = NEW_NEWS
+	ELSE
+	   WRITE(6,1100)			! Else say there are more
+	   IF (NEW) LAST_NEWS_READ(1,FOLDER_MAX) = FOLDER1_NUMBER
+	END IF
+
+	RETURN
+
+1000	FORMAT(1X,A26,2X,A17,2X,I8,2X,A12)
+1005	FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-29-1>X,2X,A1,4X,I10,'  ',I10)
+1010	FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-29-1>X,I10,2X,I10,1X,I6)
+1015    FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-36-1>X,2X,I10,2X,I10,2X,I10)
+1100	FORMAT(1X,/,' Press RETURN for more...',/)
+
+	END
+
+
+	SUBROUTINE SET_ACCESS(ACCESS)
+C
+C  SUBROUTINE SET_ACCESS
+C
+C  FUNCTION: Set access on folder for specified ID.
+C
+C  PARAMETERS:
+C	ACCESS  -  Logical: If .true., grant access, if .false. deny access
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	LOGICAL ACCESS,ALL,READONLY
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER ID*64,RESPONSE*4,NEW_NEWS_ACCESS*132
+
+	CHARACTER INPUT*132
+
+	IF (CLI$PRESENT('ALL')) THEN
+	   ALL = .TRUE.
+	ELSE
+	   ALL = .FALSE.
+	END IF
+
+	IF (CLI$PRESENT('READONLY')) THEN
+	   READONLY = .TRUE.
+	ELSE
+	   READONLY = .FALSE.
+	END IF
+
+	IF (ALL) THEN
+	   IER = CLI$GET_VALUE('ACCESS_ID',FOLDER1,LEN) ! Get folder name
+	ELSE
+	   IER = CLI$GET_VALUE('ACCESS_FOLDER',FOLDER1,LEN) ! Get folder name
+	END IF
+
+	IF (IER.EQ.%LOC(CLI$_ABSENT)) FOLDER1 = FOLDER
+	NEWS = INDEX(FOLDER1,'.').GT.0
+
+	IF (NEWS.OR.CLI$PRESENT('CLASS')) THEN
+	   IF (.NOT.CLI$PRESENT('CLASS')) THEN
+	      CALL LOWERCASE(FOLDER1)
+	   ELSE IF (FOLDER1(TRIM(FOLDER1):TRIM(FOLDER1)).NE.'.') THEN
+	      FOLDER1 = FOLDER1(:TRIM(FOLDER1))//'.'
+	   END IF
+	   CALL OPEN_BULLNEWS
+	ELSE
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	END IF
+	CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)	! See if it exists
+	OLD_FOLDER1_FLAG = FOLDER1_FLAG
+	CALL CLOSE_BULLFOLDER
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: No such folder exists.'')')
+	ELSE IF (.NOT.FOLDER_ACCESS(USERNAME,FOLDER1_FLAG,FOLDER1_OWNER)) THEN
+	   WRITE (6,
+     &	'('' ERROR: You are not able to modify access to the folder.'')')
+	ELSE IF (CLI$PRESENT('CLASS').AND..NOT.BTEST(FOLDER1_FLAG,0)) THEN
+	   WRITE (6,'('' ERROR: Must use SET NEWS/CLASS/PRIVATE.'')')
+	ELSE
+	   CALL SET_FOLDER_FILE(1)
+	   IF (NEWS) THEN
+	      CALL CHKACL(NEW_NEWS_ACCESS(FOLDER1_DESCRIP),IER)
+	   ELSE
+	      CALL CHKACL
+     &		 (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',IER)
+	   END IF
+	   IF (NEWS.AND.IER.EQ.RMS$_FNF) THEN
+	     CALL SET_PROTECTION
+	     OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &			STATUS='NEW',IOSTAT=IER)
+	     CLOSE (UNIT=3)
+	     CALL RESET_PROTECTION
+	     IF (IER.NE.0) THEN
+	        WRITE (6,'('' ERROR: Access file cannot be created.'')')
+	        RETURN
+	     END IF
+	     CALL ADD_ACL('*','NONE',IER)
+	     IF (.NOT.IER) THEN
+		WRITE(6,'('' Cannot modify access.'')')
+		CALL SYS_GETMSG(IER)
+		RETURN
+	     END IF
+	   ELSE IF (IER.EQ.RMS$_FNF) THEN
+	     FOLDER_FILE = FOLDER1_FILE
+	     REMOTE_SET_SAVE = REMOTE_SET
+	     REMOTE_SET = .FALSE.
+	     CALL OPEN_BULLFIL
+	     CALL CLOSE_BULLFIL
+	     REMOTE_SET = REMOTE_SET_SAVE
+	     IER = SS$_ACLEMPTY.OR.SS$_NORMAL
+	     CALL SET_FOLDER_FILE(0)
+	   END IF
+	   IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	     IF (.NOT.NEWS.AND.
+     &		 ((ALL.AND..NOT.READONLY).OR.(.NOT.ACCESS))) THEN
+	        WRITE (6,'('' ERROR: Folder is not a private folder.'')')
+		RETURN
+	     END IF
+	     CALL GET_INPUT_PROMPT(RESPONSE,LEN,'Access is presently'
+     &		//' unlimited. Do you want to change this? (Y/N): ')
+	     IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+	       WRITE (6,'('' Access was not changed.'')')
+	       RETURN
+	     ELSE
+	       FOLDER1_FLAG = IBSET(FOLDER1_FLAG,0)
+	       IF (READONLY.AND.ALL) THEN
+	          CALL ADD_ACL('*','R',IER)
+	       ELSE IF (.NOT.ALL) THEN
+	          CALL ADD_ACL('*','NONE',IER)
+	       END IF
+	       IF (.NOT.NEWS) CALL ADD_ACL(FOLDER1_OWNER,'R+W+C',IER)
+	       IF (ALL) THEN		! All finished, so exit
+	        WRITE (6,'('' Access to folder has been modified.'')')
+		GOTO 100
+	       END IF
+	     END IF
+	   END IF
+
+	   IF (ALL) THEN
+	      IF (ACCESS) THEN
+		 CALL DEL_ACL(' ','R+W',IER)
+	         IF (READONLY) THEN
+	            CALL ADD_ACL('*','R',IER)
+	         ELSE IF (.NOT.NEWS) THEN
+		    FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+	   	    IF (.NOT.NEWS.AND.REMOTE_SET) THEN
+		       CALL SET_FOLDER_FILE(1)
+		       FOLDER_FILE = FOLDER1_FILE
+		       REMOTE_SET_SAVE = REMOTE_SET
+		       REMOTE_SET = .FALSE.
+		       CALL OPEN_BULLDIR
+		       CALL OPEN_BULLFIL
+		       CALL CLOSE_BULLFIL_DELETE
+		       CALL CLOSE_BULLDIR_DELETE
+		       REMOTE_SET = REMOTE_SET_SAVE
+		       CALL SET_FOLDER_FILE(0)
+		    END IF
+		 END IF
+	      ELSE
+		 CALL DEL_ACL('*','R',IER)
+	      END IF
+	      IF (.NOT.IER) THEN
+		 WRITE(6,'('' Cannot modify access.'')')
+		 CALL SYS_GETMSG(IER)
+	      END IF
+	   END IF
+
+	   DO WHILE (CLI$GET_VALUE('ACCESS_ID',INPUT,ILEN)
+     &	    .NE.%LOC(CLI$_ABSENT).AND..NOT.ALL)
+	      IER = SYS_TRNLNM(INPUT,INPUT)
+	      IF (INPUT(:1).EQ.'@') THEN
+		 ILEN = INDEX(INPUT,',') - 1
+		 IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+		 OPEN (UNIT=3,STATUS='OLD',FILE=INPUT(2:ILEN),
+     &			DEFAULTFILE='.DIS',IOSTAT=IER)
+		 IF (IER.NE.0) THEN
+		    WRITE (6,'('' ERROR: Cannot find file '',A)')
+     &					INPUT(2:ILEN)
+		    RETURN
+		 END IF
+		 READ (3,'(A)',IOSTAT=IER) INPUT
+		 IF (IER.NE.0) THEN
+		    CLOSE (UNIT=3)
+		    INPUT = ' '
+		 ELSE
+		    FILE_OPEN = .TRUE.
+		 END IF
+	      ELSE
+		 FILE_OPEN = .FALSE.
+	      END IF
+	      DO WHILE (TRIM(INPUT).GT.0)
+	         COMMA = INDEX(INPUT,',')
+		 IF (INDEX(INPUT,'[').EQ.0.AND.INDEX(INPUT,']').GT.0.AND.
+     &		    ID(:1).EQ.'[') INPUT = ID(:TRIM(ID))//','//INPUT
+		 IF (INPUT(:1).EQ.'['.AND.INDEX(INPUT,']').GT.0)
+     &		    COMMA = INDEX(INPUT,']') + 1
+		 IF (INPUT(:1).EQ.'"'.AND.INDEX(INPUT(2:),'"').GT.0)
+     &		    COMMA = INDEX(INPUT(2:),'"') + 2
+		 IF (INPUT(:1).EQ.'['.AND.INDEX(INPUT,']').EQ.0) COMMA = 0
+	         IF (COMMA.GT.0) THEN
+		    ID = INPUT(1:COMMA-1)
+		    INPUT = INPUT(COMMA+1:)
+	            ILEN = TRIM(ID)
+	         ELSE
+		    ID = INPUT
+		    INPUT = ' '
+	            ILEN = TRIM(ID)
+	         END IF
+ 	         IF (.NOT.NEWS.AND.ID.EQ.FOLDER1_OWNER) THEN
+	            WRITE (6,'('' ERROR: Cannot modify access'',
+     &			       '' for owner of folder.'')')
+		 ELSE IF (ID(:1).NE.'['.OR.INDEX(ID,']').NE.0) THEN
+		    IF (ILEN.EQ.0) THEN
+		       IER = SS$_IVIDENT
+		    ELSE IF (ACCESS) THEN
+	               IF (READONLY) THEN
+	                  CALL ADD_ACL(ID,'R',IER)
+		       ELSE
+	                  CALL ADD_ACL(ID,'R+W',IER)
+		       END IF
+	            ELSE
+	               CALL DEL_ACL(ID,'R+W',IER)
+	               IF (.NOT.IER) CALL DEL_ACL(ID,'R',IER)
+	            END IF
+	            IF (.NOT.IER) THEN
+		       WRITE(6,'('' Cannot modify access for '',A,
+     &					''.'')') ID(:ILEN)
+		       CALL SYS_GETMSG(IER)
+		    ELSE
+		       WRITE(6,'('' Access modified for '',A,''.'')')
+     &				ID(:ILEN)
+		    END IF
+		 END IF
+	         IF (TRIM(INPUT).EQ.0.AND.FILE_OPEN) THEN
+		    READ (3,'(A)',IOSTAT=IER) INPUT
+		    IF (IER.NE.0) THEN
+		       CLOSE (UNIT=3)
+		       INPUT = ' '
+		       FILE_OPEN = .FALSE.
+		    END IF
+		 END IF
+	      END DO
+	   END DO
+	   
+100	   IF (OLD_FOLDER1_FLAG.NE.FOLDER1_FLAG) THEN
+	      IF (NEWS) THEN
+	         CALL OPEN_BULLNEWS
+	      ELSE
+	         CALL OPEN_BULLFOLDER
+	      END IF
+	      OLD_FOLDER1_FLAG = FOLDER1_FLAG
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	      FOLDER1_FLAG = OLD_FOLDER1_FLAG
+	      CALL REWRITE_FOLDER_FILE_TEMP(IER)
+	      CALL CLOSE_BULLFOLDER
+	   END IF
+	END IF
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CHKACL(FILENAME,IERACL)
+C
+C  SUBROUTINE CHKACL
+C
+C  FUNCTION: Checks ACL of given file.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C	IERACL   - Error returned for attempt to open file.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) FILENAME
+
+	INCLUDE '($ACLDEF)'
+	INCLUDE '($SSDEF)'
+
+	CHARACTER*256 ACLENT
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(256,ACL$C_READACL,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IERACL=SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST),,,)
+
+	IF (IERACL.EQ.SS$_ACLEMPTY) THEN
+	   IERACL = SS$_NORMAL.OR.IERACL
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CHECK_ACCESS(FILENAME,USERNAME,READ_ACCESS,WRITE_ACCESS)
+C
+C  SUBROUTINE CHECK_ACCESS
+C
+C  FUNCTION: Checks ACL of given file.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C	USERNAME - Name of user to check access for.
+C	READ_ACCESS - Error returned indicating read access.
+C	WRITE_ACCESS - Error returned indicating write access.
+C		       If initially set to -1, indicates just
+C		       folder for read access.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER FILENAME*(*),USERNAME*(*),ACE*256,OUTPUT*80
+
+	INCLUDE '($ACLDEF)'
+	INCLUDE '($CHPDEF)'
+	INCLUDE '($ARMDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,CHP$_FLAGS,%LOC(FLAGS))
+	CALL ADD_2_ITMLST(4,CHP$_ACCESS,%LOC(ACCESS))
+	CALL ADD_2_ITMLST(LEN(ACE),CHP$_MATCHEDACE,%LOC(ACE))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	FLAGS = 0		! Default is no access
+
+	ACCESS = ARM$M_READ	! Check if user has read access
+	READ_ACCESS=SYS$CHECK_ACCESS(ACL$C_FILE,FILENAME,USERNAME,
+     &		%VAL(ACL_ITMLST))
+
+
+	IF (ICHAR(ACE(:1)).NE.0) THEN
+	   CALL SYS$FORMAT_ACL(ACE,,OUTPUT,,,,)
+	   IF (INDEX(OUTPUT,'=*').NE.0.AND.
+     &		INDEX(OUTPUT,'READ').EQ.0) READ_ACCESS = 0
+	ELSE IF (ICHAR(ACE(:1)).EQ.0.AND.READ_ACCESS) THEN
+	   READ_ACCESS = 0
+	END IF
+
+	IF (WRITE_ACCESS.EQ.-1) THEN	! Only check read access
+	   RETURN
+	ELSE IF (READ_ACCESS.EQ.0) THEN	! If no read access, then of
+	   WRITE_ACCESS = 0		! course there is no write access.
+	   RETURN
+	END IF
+
+	ACCESS = ARM$M_WRITE	! Check if user has write access
+	WRITE_ACCESS=SYS$CHECK_ACCESS(ACL$C_FILE,FILENAME,USERNAME,
+     &		%VAL(ACL_ITMLST))
+
+	IF (ICHAR(ACE(:1)).NE.0) THEN
+	   CALL SYS$FORMAT_ACL(ACE,,OUTPUT,,,,)
+	   IF (INDEX(OUTPUT,'=*').NE.0.AND.
+     &		INDEX(OUTPUT,'WRITE').EQ.0) WRITE_ACCESS = 0
+	ELSE IF (ICHAR(ACE(:1)).EQ.0.AND.WRITE_ACCESS) THEN
+	   WRITE_ACCESS = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOWACL(FILENAME)
+C
+C  SUBROUTINE SHOWACL
+C
+C  FUNCTION: Shows users who are allowed to read private bulletin.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER*(*) FILENAME
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,ACL$C_ACLLENGTH,%LOC(ACLLENGTH))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST),,,)
+
+	CALL LIB$GET_VM(ACLLENGTH+8,ACLSTR)
+	CALL MAKE_CHAR(%VAL(ACLSTR),ACLLENGTH,ACLLENGTH)
+
+	CALL READACL(FILENAME,%VAL(ACLSTR),ACLLENGTH)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE FOLDER_FILE_ROUTINES
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) KEY_NAME
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_OPEN/ NEWS_OPEN
+
+	ENTRY WRITE_FOLDER_FILE(IER)
+
+	IF (NEWS_OPEN) CALL FOLDER_TO_NEWS
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      WRITE (7,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      WRITE (7,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	RETURN
+
+        ENTRY WRITE_FOLDER_FILE_TEMP(IER)
+
+        IF (NEWS_OPEN) CALL FOLDER1_TO_NEWS
+
+        DO WHILE (REC_LOCK(IER))
+           IF (NEWS_OPEN) THEN
+              WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+           ELSE
+              WRITE (7,IOSTAT=IER) FOLDER1_COM
+           END IF
+        END DO
+
+        RETURN
+
+	ENTRY REWRITE_FOLDER_FILE(IER)
+
+	IF (NEWS_OPEN) THEN
+	   CALL FOLDER_TO_NEWS
+	   REWRITE (7,IOSTAT=IER) NEWS_FOLDER_COM
+	ELSE
+	   REWRITE (7,IOSTAT=IER) FOLDER_COM
+	END IF
+
+	RETURN
+
+	ENTRY REWRITE_FOLDER_FILE_TEMP(IER) 
+
+	IF (NEWS_OPEN) THEN
+	   CALL FOLDER1_TO_NEWS
+	   REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	ELSE
+	   REWRITE (7,IOSTAT=IER) FOLDER1_COM
+	END IF
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_TEMP(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM(KEY_NUMBER,IER)
+
+	SAVE_FOLDER_NUMBER = FOLDER_NUMBER
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM_GT(KEY_NUMBER,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM_TEMP(KEY_NUMBER,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM_GT_TEMP(KEY_NUMBER,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAME_TEMP(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAMEGE_TEMP(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGE=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEYGE=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAMEGT_TEMP(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGT=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEYGT=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAME(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	RETURN
+
+	END
+
+
+	SUBROUTINE USER_FILE_ROUTINES
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE '($FORIOSDEF)'
+
+	CHARACTER*(*) KEY_NAME
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER*12 SAVE_USERNAME
+
+	ENTRY READ_USER_FILE(IER)
+
+	SAVE_USERNAME = USERNAME
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,IOSTAT=IER) USER_ENTRY
+	END DO
+
+	TEMP_USER = USERNAME
+	USERNAME = SAVE_USERNAME
+
+	RETURN
+
+	ENTRY READ_USER_FILE_KEYNAME(KEY_NAME,IER)
+
+	SAVE_USERNAME = USERNAME
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY=KEY_NAME,IOSTAT=IER) USER_ENTRY
+	END DO
+
+	USERNAME = SAVE_USERNAME
+	TEMP_USER = KEY_NAME
+
+	RETURN
+
+	ENTRY READ_USER_FILE_HEADER(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='            ',IOSTAT=IER) USER_HEADER
+	   IF (IER.EQ.FOR$IOS_ATTACCNON) THEN
+	      WRITE (4,FMT=USER_FMT,IOSTAT=IER)
+     &		 USER_HEADER_KEY,NEWEST_BTIM,
+     &	         BBOARD_BTIM,PRV$M_OPER.OR.PRV$M_CMKRNL.OR.
+     &	         PRV$M_SETPRV,(0,I=1,FLONG*4-1)
+	      IER = FOR$IOS_SPERECLOC
+	   END IF
+	END DO
+
+	RETURN
+
+	ENTRY WRITE_USER_FILE_NEW(IER)
+
+	DO I=1,FLONG
+	   SET_FLAG(I) = SET_FLAG_DEF(I)
+	   BRIEF_FLAG(I) = BRIEF_FLAG_DEF(I)
+	   NOTIFY_FLAG(I) = NOTIFY_FLAG_DEF(I)
+	END DO
+
+	ENTRY WRITE_USER_FILE(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   WRITE (4,IOSTAT=IER) USER_ENTRY
+	END DO
+
+	RETURN
+
+	END
+
+
+
+	CHARACTER*(*) FUNCTION NEW_NEWS_ACCESS(IFILE)
+ 
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER IFILE*(*),FILE*80
+
+        FILE = IFILE
+	
+	DO I=1,TRIM(FILE)
+	   IF (FILE(I:I).EQ.'.') FILE(I:I) = '_'
+	END DO
+
+	FILE = FILE(:INDEX(FILE,' ')-1)
+	IF (FILE(TRIM(FILE):TRIM(FILE)).EQ.'_') FILE = FILE(:TRIM(FILE)-1)
+
+	NEW_NEWS_ACCESS = 
+     &	   NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//FILE(:TRIM(FILE))
+     &	   //'.ACCESS'
+
+	RETURN
+	END
+
+
+
+
+	CHARACTER*(*) FUNCTION NEWS_ACCESS(IFILE)
+ 
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER IFILE*(*),FILE*80
+
+        FILE = IFILE
+	
+	DO I=1,TRIM(FILE)
+	   IF (FILE(I:I).EQ.'.') FILE(I:I) = '_'
+	END DO
+
+	FILE = FILE(:INDEX(FILE,' ')-1)
+	IF (FILE(TRIM(FILE):TRIM(FILE)).EQ.'_') FILE = FILE(:TRIM(FILE)-1)
+
+	C = 0
+
+	DO WHILE (TRIM(FILE).GT.0.AND..NOT.LIB$FIND_FILE(
+     &	   NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//FILE(:TRIM(FILE))
+     &	   //'.ACCESS',NEWS_ACCESS,C))
+	   L = LAST_INDEX(FILE,'_')-1
+	   IF (L.LE.0) THEN
+	      FILE = ' '
+	   ELSE
+	      FILE = FILE(:L)
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION LAST_INDEX(INPUT,FIND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,FIND
+
+        F = LEN(FIND)
+
+	DO LAST_INDEX=LEN(INPUT)-F+1,F,-1
+           IF (INPUT(LAST_INDEX:LAST_INDEX+F-1).EQ.FIND) RETURN
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NEXT_GROUP(MATCH,FOLDER_MATCH,MLEN,FOUND,STORED,
+     &				  STAT,IER,ACTIVE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	CHARACTER*(*) STAT,FOLDER_MATCH
+
+	CHARACTER NEWS_ACCESS*132
+
+	FOUND = .FALSE.
+	STAR = INDEX(FOLDER_MATCH,'*')
+	ONE = STAR.EQ.0.AND.TRIM(FOLDER_MATCH).GT.0
+	START = .FALSE.
+	IF (STAR.GT.1)
+     &	   START = FOLDER_MATCH(:STAR-1).NE.FOLDER1(:STAR-1)
+	STARTNOW = START
+
+	DO WHILE (FLAG.NE.1.AND.IER.EQ.0.AND..NOT.FOUND) 
+	   IF (ONE) THEN
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &		(FOLDER_MATCH(:TRIM(FOLDER_MATCH)),IER)
+	      FOLDER_MATCH = ' '
+	   ELSE IF (STARTNOW) THEN 
+	      CALL READ_FOLDER_FILE_KEYNAMEGE_TEMP
+     &				       (FOLDER_MATCH(:STAR-1),IER)
+	      STARTNOW = .FALSE.
+	   ELSE
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+	   END IF
+	   J = INDEX(FOLDER1_DESCRIP,' ')
+	   IF (J.GT.0) THEN
+	      STAT(:1) = FOLDER1_DESCRIP(J+1:)
+	   ELSE
+	      STAT = ' '
+	      J = TRIM(FOLDER1_DESCRIP) + 1
+	   END IF
+	   IF (IER.EQ.0.AND.(.NOT.ACTIVE.OR.(STAT(:1).NE.'x'.AND.
+     &		.NOT.BTEST(FOLDER1_FLAG,9))).AND.
+     &		(.NOT.STORED.OR.BTEST(FOLDER1_FLAG,8)).AND.
+     &		(ONE.OR..NOT.MATCH.OR.STR$MATCH_WILD(FOLDER1_DESCRIP
+     &		(:J-1),FOLDER_MATCH(:MLEN)))) THEN
+	      IF (BTEST(FOLDER1_FLAG,0)) THEN
+		 IF (OLD_BUFFER.NE.NEWS_ACCESS(FOLDER1_DESCRIP)) THEN
+		    OLD_BUFFER = NEWS_ACCESS(FOLDER1_DESCRIP)
+		    CALL CHKACL(OLD_BUFFER(:TRIM(OLD_BUFFER)),IER2)
+	   	    IF (IER2.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+		       CALL CHECK_ACCESS(OLD_BUFFER
+     &			 (:TRIM(OLD_BUFFER)),USERNAME,FOUND1,-1)
+ 		    ELSE
+		       FOUND1 = .TRUE.
+		    END IF
+		 END IF
+		 FOUND = FOUND1
+	      ELSE
+		 FOUND = .TRUE.
+	      END IF
+	   ELSE IF (IER.EQ.0.AND.START) THEN 
+	      IF (FOLDER_MATCH(:STAR-1).NE.FOLDER1(:STAR-1)) RETURN
+	   END IF
+	   IF (ONE) RETURN
+	END DO
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin6.for b/decus/vmslt00a/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..92a761ff81ab07b38fe8a3ec9a2f72d4adc521ad
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin6.for
@@ -0,0 +1,2835 @@
+C
+C  BULLETIN6.FOR, Version 11/2/98
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE CLOSE_FILE
+C
+C  SUBROUTINE CLOSE_FILE
+C
+C  FUNCTION: To close out the bulletin files and enable CTRL-C & -Y
+C
+
+        IMPLICIT INTEGER (A-Z)
+
+	COMMON /BULLFIL/ BULLFIL
+	DATA BULLFIL /0/
+
+	DATA LUN /0/
+
+	ENTRY CLOSE_BULLINF
+	LUN = LUN + 1			! Unit = 9
+
+	ENTRY CLOSE_SYSUAF
+	LUN = LUN + 1			! Unit = 8
+
+	ENTRY CLOSE_BULLNEWS
+	ENTRY CLOSE_BULLFOLDER
+	LUN = LUN + 3			! Unit = 7
+
+	ENTRY CLOSE_BULLUSER
+	LUN = LUN + 2			! Unit = 4
+
+	ENTRY CLOSE_BULLDIR
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY CLOSE_BULLFIL
+	LUN = LUN + 1			! Unit = 1
+
+	CALL ENABLE_CTRL
+
+	CLOSE (UNIT=LUN)
+
+        IF (LUN.EQ.1.AND.BULLFIL.GT.0) BULLFIL = -BULLFIL
+
+	LUN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE CLOSE_FILE_DELETE
+
+	IMPLICIT INTEGER (A-Z)
+
+        COMMON /BULLFIL/ BULLFIL
+
+	DATA LUN /0/
+
+	ENTRY CLOSE_BULLDIR_DELETE
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY CLOSE_BULLFIL_DELETE
+	LUN = LUN + 1			! Unit = 1
+
+	CALL ENABLE_CTRL
+
+	CLOSE (UNIT=LUN,STATUS='DELETE')
+
+        IF (LUN.EQ.1.AND.BULLFIL.GT.0) BULLFIL = -BULLFIL
+
+	LUN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE OPEN_FILE(UNIT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+        COMMON /NEWS_OPEN/ NEWS_OPEN
+
+        COMMON /BULLFIL/ BULLFIL
+
+	COMMON /NEWSLIST/ NEWSLIST
+
+	COMMON /DIRLIST/ DIRLIST
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+
+	DATA LUN /0/
+
+	LUN = UNIT - 14			! 14 gets added to LUN
+
+	ENTRY OPEN_BULLNEWS
+	LUN = LUN + 5			! Unit = 14
+
+	ENTRY OPEN_BULLINF
+	LUN = LUN + 1			! Unit = 9
+
+	ENTRY OPEN_SYSUAF
+	LUN = LUN + 1			! Unit = 8
+
+	ENTRY OPEN_BULLFOLDER
+	LUN = LUN + 3			! Unit = 7
+
+	ENTRY OPEN_BULLUSER
+	LUN = LUN + 2			! Unit = 4
+
+	ENTRY OPEN_BULLDIR
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY OPEN_BULLFIL
+	LUN = LUN + 1			! Unit = 1
+
+	IER = 0
+
+	NTRIES = 0
+
+	CALL SET_PROTECTION
+
+	CALL DISABLE_CTRL		! No breaks while file is open
+
+	IF (LUN.EQ.2.AND.REMOTE_SET.EQ.4) THEN
+	   TRY = 0
+	   CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    IF (DIRLIST) THEN 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      BUFFERCOUNT=127,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    ELSE 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    END IF
+
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU.AND.TRY.EQ.0) THEN
+	       BULLNEWSDIR_FILE = 'BULLNEWSDIR.DAT'
+	       CALL ADD_DIRECTORY(BULLNEWSDIR_FILE)
+	       TRY = 1
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	    ELSE IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+	       OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	        STATUS='NEW',FORM='UNFORMATTED',SHARED,
+     &	        RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	        KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	        57:64:CHARACTER),ACCESS='KEYED')
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN.OR.
+     &		IER.EQ.FOR$IOS_INVKEYSPE) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       LUN = 0
+	       CALL CONVERT_BULLNEWSDIR
+	       NTRIES = 0
+	       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+            ELSE IF (IER.EQ.FOR$IOS_OPEFAI) THEN
+	       CALL ERRSNS(IDUMMY,IER1)
+               IF (IER1.EQ.RMS$_DNF) THEN
+	          IER2 =  LIB$CREATE_DIR(BULLNEWSDIR_FILE(:
+     &			INDEX(BULLNEWSDIR_FILE,']')))
+	          IF (IER2) IDUMMY = FILE_LOCK(IER,IER1)
+	       END IF
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   DIR_NUM = -1
+	ELSE IF (LUN.EQ.2.AND..NOT.REMOTE_SET) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	       OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	        //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	        RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	        KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	    ELSE IF (IER.EQ.0) THEN
+	       INQUIRE(UNIT=2,RECORDSIZE=ASK_SIZE)
+	       IF (ASK_SIZE.NE.DIR_RECORD_LENGTH/4) THEN
+	          CLOSE (UNIT=2)
+	          IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	          CALL CONVERT_BULLFILES
+		  NTRIES = 0
+	       END IF
+	    ELSE IF (IER.EQ.FOR$IOS_INCFILORG) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLDIRS
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   DIR_NUM = -1
+	END IF
+
+	IF (LUN.EQ.1.AND..NOT.REMOTE_SET) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    IF (REMOTE_SET.EQ.4) THEN
+	      IF (BULLFIL.NE.1) CALL SET_BULLFIL_NAME
+	      OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='UNKNOWN',IOSTAT=IER,SHARED,
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	      FORM='UNFORMATTED')
+	      IF (IER.EQ.0) THEN
+	         DO WHILE (REC_LOCK(IER2))
+                    READ (1'1,IOSTAT=IER2) NBLOCK
+	         END DO
+                 IF (IER2.NE.0) THEN
+                    NBLOCK = 1
+                    WRITE (1'1,IOSTAT=IER2) NBLOCK
+		 END IF
+                 BULLFIL = 1
+              END IF
+            ELSE
+	      OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='UNKNOWN',IOSTAT=IER,
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	      FORM='UNFORMATTED')
+            END IF
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLFILE
+	       NTRIES = 0
+            ELSE IF (IER.EQ.FOR$IOS_OPEFAI) THEN
+	       CALL ERRSNS(IDUMMY,IER1)
+               IF (IER1.EQ.RMS$_DNF) THEN
+	          IER2 =  LIB$CREATE_DIR(
+     &				FOLDER_FILE(:INDEX(FOLDER_FILE,']')))
+	          IF (IER2) IDUMMY = FILE_LOCK(IER,IER1)
+	       END IF
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	END IF
+
+	IF (LUN.EQ.4) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=7+FLONG*4,
+     &	     ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	     KEY=(1:12:CHARACTER))
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	     OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='UNKNOWN',
+     &	      ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=28+FLONG*16,
+     &	      FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	      KEY=(1:12:CHARACTER))
+	     WRITE (4,FMT=USER_FMT) USER_HEADER_KEY,NEWEST_BTIM,
+     &	      BBOARD_BTIM,PRV$M_OPER.OR.PRV$M_CMKRNL.OR.
+     &	      PRV$M_SETPRV,(0,I=1,FLONG*4-1)
+	     CLOSE (UNIT=4)
+	     IDUMMY = FILE_LOCK(IER,IER1)
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	     IDUMMY = FILE_LOCK(IER,IER1)
+	     CALL CONVERT_USERFILE
+	     NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	END IF
+
+	IF (LUN.EQ.7) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	     RECORDSIZE=FOLDER_RECORD/4,
+     &	     ORGANIZATION='INDEXED',IOSTAT=IER)
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	      FOLDER1 = 'GENERAL'
+	      FOLDER1_OWNER = 'SYSTEM'
+	      FOLDER1_DESCRIP = 'Default general bulletin folder.'
+	      FOLDER1_BBOARD = 'NONE'
+	      FOLDER1_BBEXPIRE = 14
+	      NBULL = 0
+	      OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='UNKNOWN',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=FOLDER_RECORD,
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER2,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER))
+              CALL SYS_BINTIM('5-NOV-1982 00:00:00.00',
+     &				NEWS_F_NEWEST_BTIM)
+              CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,FOLDER1_CREATED_DATE)
+	      WRITE (7,FMT=FOLDER_FMT,IOSTAT=IER2)
+     &		FOLDER1,0,FOLDER1_CREATED_DATE,FOLDER1_OWNER,FOLDER1_DESCRIP
+     &		,FOLDER1_BBOARD,FOLDER1_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &		,NBULL,F_NEWEST_BTIM,4,0,F_NEWEST_NOSYS_BTIM,0,0,0
+						! 4 means system folder
+	      CLOSE (UNIT=7)
+	      IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	      IDUMMY = FILE_LOCK(IER,IER1)
+	      CALL CONVERT_BULLFOLDER(BULLFOLDER_FILE)
+	      NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .FALSE.
+	END IF
+
+	IF (LUN.EQ.14) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+            IF (NEWSLIST) THEN
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	        BUFFERCOUNT=127,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER)
+	    ELSE
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER)
+            END IF
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	      OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='UNKNOWN',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD,
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER2,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER,
+     &          57:64:CHARACTER:DESCENDING))
+	      CLOSE (UNIT=7)
+	      IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	      IDUMMY = FILE_LOCK(IER,IER1)
+	      CALL CONVERT_BULLNEWS(BULLNEWS_FILE)
+	      NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.10) CALL TIMER_ERR(LUN)
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .TRUE.
+	END IF
+
+	IF (LUN.EQ.9) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='UNKNOWN',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=FOLDER_MAX*2+3,
+     &	     IOSTAT=IER,ORGANIZATION='INDEXED',
+     &	     KEY=(1:12:CHARACTER))
+	     IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_INFFILE
+	       NTRIES = 0
+	     END IF
+	     NTRIES = 0
+	     IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'(
+     &	    '' Cannot open file in OPEN_FILE, unit = '',I)') LUN
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	   CALL ENABLE_CTRL_EXIT	! Enable CTRL-Y & -C & EXIT
+	END IF
+
+	LUN = 0
+
+	CALL RESET_PROTECTION
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE TIMER_ERR(UNIT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*14 NAMES(6)
+	DATA NAMES/'directory','message','BULLUSER.DAT','BULLFOLDER.DAT',
+     &			'BULLINF.DAT','BULLNEWS.DAT'/
+	INTEGER NAME(14)
+	DATA NAME/2,1,0,3,0,0,4,0,5,0,0,0,0,6/
+
+	IF (TEST_BULLCP().NE.2) THEN	! If BULLCP process, don't log error
+	   WRITE(6,'('' ERROR: Unable to open file: '',A)')
+     &			NAMES(NAME(UNIT))(:TRIM(NAMES(NAME(UNIT))))
+	   IF (UNIT.EQ.14) THEN 
+	      WRITE (6,'('' Database conversion in progress.  Try later.'')')
+	   ELSE
+	      WRITE (6,'('' Please try again later.'')')
+	   END IF
+	END IF
+
+	CALL ENABLE_CTRL_EXIT		! No breaks while file is open
+	END
+
+
+
+	SUBROUTINE OPEN_FILE_SHARED
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+        COMMON /NEWS_OPEN/ NEWS_OPEN
+
+        COMMON /BULLFIL/ BULLFIL
+
+	EXTERNAL LNM_MODE_EXEC,ENABLE_CTRL_EXIT
+C
+C  The following 2 files were used prior to V1.1.
+C
+	CHARACTER*80 BULLDIR_FILE /'BULL_DIR:BULLDIR.DAT'/
+	CHARACTER*80 BULLETIN_FILE /'BULL_DIR:BULLETIN.DAT'/
+
+	COMMON /NEWSLIST/ NEWSLIST
+	DATA NEWSLIST/0/
+
+	COMMON /DIRLIST/ DIRLIST
+	DATA DIRLIST/0/
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+  
+	CHARACTER*44 SAVE_FOLDER
+	DATA SAVE_BLOCK/-1/
+
+	CHARACTER*14 NAMES(6)
+	DATA NAMES/'directory','message','BULLUSER.DAT','BULLFOLDER.DAT',
+     &			'BULLINF.DAT','BULLNEWS.DAT'/
+	INTEGER NAME(14)
+	DATA NAME/2,1,0,3,0,0,4,0,5,0,0,0,0,6/
+
+	DATA LUN /0/
+
+	ENTRY OPEN_BULLNEWS_SHARED
+	LUN = LUN + 5			! Unit = 14
+
+	ENTRY OPEN_BULLINF_SHARED
+	LUN = LUN + 1			! Unit = 9
+
+	ENTRY OPEN_SYSUAF_SHARED
+	LUN = LUN + 1			! Unit = 8
+
+	ENTRY OPEN_BULLFOLDER_SHARED
+	LUN = LUN + 3			! Unit = 7
+
+	ENTRY OPEN_BULLUSER_SHARED
+	LUN = LUN + 2			! Unit = 4
+
+	ENTRY OPEN_BULLDIR_SHARED
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY OPEN_BULLFIL_SHARED
+	LUN = LUN + 1			! Unit = 1
+
+	IER = 0
+
+	NTRIES = 0
+
+	CALL DISABLE_CTRL
+
+	IF (LUN.EQ.2.AND.REMOTE_SET.EQ.4) THEN
+	   CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    IF (DIRLIST) THEN 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      BUFFERCOUNT=127,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    ELSE 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    END IF
+	    IF (IER.EQ.FOR$IOS_INCRECLEN.OR.
+     &		IER.EQ.FOR$IOS_INVKEYSPE) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       LUN = 0
+	       CALL CONVERT_BULLNEWSDIR
+	       LUN = 2
+	       NTRIES = 0
+	       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+            ELSE IF (IER.EQ.FOR$IOS_OPEFAI) THEN
+	       CALL ERRSNS(IDUMMY,IER1)
+               IF (IER1.EQ.RMS$_DNF) THEN
+	          IER1 =  LIB$CREATE_DIR(BULLNEWSDIR_FILE(:
+     &			INDEX(BULLNEWSDIR_FILE,']')))
+	          IF (IER1) IDUMMY = FILE_LOCK(IER,IER1)
+	       END IF
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   DIR_NUM = -1
+	ELSE IF (LUN.EQ.2.AND..NOT.REMOTE_SET) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU.AND.(FOLDER_NUMBER.EQ.0
+     &		.OR.FOLDER.EQ.'GENERAL')) THEN
+	       IER2 = LIB$RENAME_FILE(BULLETIN_FILE,'GENERAL.BULLFIL')
+	       IER2 = LIB$RENAME_FILE(BULLDIR_FILE,'GENERAL.BULLDIR')
+	       IF (IER2) IDUMMY = FILE_LOCK(IER,IER1) ! Don't break out of loop
+	    ELSE IF (IER.EQ.0) THEN
+	       INQUIRE(UNIT=2,RECORDSIZE=ASK_SIZE)
+	       IF (ASK_SIZE.NE.DIR_RECORD_LENGTH/4) THEN
+	          CLOSE (UNIT=2)
+	          IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	          CALL CONVERT_BULLFILES
+		  NTRIES = 0
+	       END IF
+	    ELSE IF (IER.EQ.FOR$IOS_INCFILORG) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLDIRS
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	   DIR_NUM = -1
+	END IF
+
+	IF (LUN.EQ.1.AND.REMOTE_SET.AND.(SAVE_BLOCK.NE.BLOCK.OR.
+     &		SAVE_FOLDER.NE.FOLDER)) THEN
+	   CALL REMOTE_READ_MESSAGE(BULL_POINT,IER)
+	   IF (IER.GT.0) THEN
+	      CALL ERROR_AND_EXIT
+	   ELSE
+	      SAVE_BLOCK = BLOCK
+	      SAVE_FOLDER = FOLDER
+	      CALL GET_REMOTE_MESSAGE(IER)
+	      IER = 0
+	   END IF
+	ELSE IF (LUN.EQ.1.AND..NOT.REMOTE_SET) THEN
+	   SAVE_BLOCK = -1
+	   IF (REMOTE_SET.EQ.4.AND.BULLFIL.NE.2) CALL SET_BULLFIL_NAME
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	     OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='OLD',
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	      FORM='UNFORMATTED',IOSTAT=IER,SHARED,READONLY)
+	    IF (REMOTE_SET.EQ.4) THEN
+	      IF (IER.EQ.0) THEN
+	         DO WHILE (REC_LOCK(IER2))
+                    READ (1'1,IOSTAT=IER2) NBLOCK
+	         END DO
+                 IF (IER2.NE.0) NBLOCK = 1
+                 BULLFIL = 2
+              END IF
+            END IF
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLFILE
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	END IF
+
+	IF (LUN.EQ.4) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='OLD',
+     &	    ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=7+FLONG*4,
+     &	    IOSTAT=IER,ORGANIZATION='INDEXED',SHARED,
+     &	    KEY=(1:12:CHARACTER))
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)
+	       CALL CONVERT_USERFILE
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	END IF
+
+	IF (LUN.EQ.7) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='OLD',
+     &	    RECORDSIZE=FOLDER_RECORD/4,
+     &	    ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	    IOSTAT=IER,ORGANIZATION='INDEXED',SHARED)
+
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)
+	       CALL CONVERT_BULLFOLDER(BULLFOLDER_FILE)
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .FALSE.
+	END IF
+
+	IF (LUN.EQ.14) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+            IF (NEWSLIST) THEN
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	       ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	       BUFFERCOUNT=127,
+     &	       RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	       IOSTAT=IER,ORGANIZATION='INDEXED',SHARED)
+	    ELSE
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	       ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	       RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	       IOSTAT=IER,ORGANIZATION='INDEXED',SHARED)
+            END IF
+
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	      IDUMMY = FILE_LOCK(IER,IER1)
+	      CALL CONVERT_BULLNEWS(BULLNEWS_FILE)
+	      NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.10) CALL ENABLE_CTRL_EXIT
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .TRUE.
+	END IF
+
+	IF (LUN.EQ.8) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=8,FILE='SYSUAF',DEFAULTFILE='SYS$SYSTEM:SYSUAF.DAT',
+     &       ACCESS='KEYED',FORM='UNFORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,IOSTAT=IER,SHARED,
+     &	     USEROPEN=LNM_MODE_EXEC)
+	   END DO
+	END IF
+
+	IF (LUN.EQ.9) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	     OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='OLD',
+     &	      ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	      RECORDSIZE=FOLDER_MAX*2+3,
+     &	      IOSTAT=IER,ORGANIZATION='INDEXED',SHARED,
+     &	      KEY=(1:12:CHARACTER))
+	     IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_INFFILE
+	       NTRIES = 0
+	     END IF
+	     NTRIES = NTRIES + 1
+	     IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	END IF
+
+	IF (IER.EQ.FOR$IOS_FILNOTFOU.AND.LUN.NE.8) THEN
+	   CALL OPEN_FILE(LUN)
+	ELSE IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Cannot open '',A)')
+     &			NAMES(NAME(LUN))(:TRIM(NAMES(NAME(LUN))))
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   IF (LUN.EQ.2.AND.REMOTE_SET.EQ.4) WRITE(6,'(1X,A)') 
+     &	      BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))
+	   WRITE(6,'(1X,A)') FOLDER_FILE(:TRIM(FOLDER_FILE)) 
+	   WRITE(6,'(1X,A)')USERNAME
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	   CALL ENABLE_CTRL_EXIT
+	END IF
+
+	LUN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE RESET_PROTECTION
+
+	IMPLICIT INTEGER (A-Z)
+
+	DATA PROT_LEVEL /0/
+
+	PROT_LEVEL = PROT_LEVEL - 1
+	IF (PROT_LEVEL.GT.0) RETURN
+
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	RETURN
+
+	ENTRY SET_PROTECTION
+
+	PROT_LEVEL = PROT_LEVEL + 1
+	IF (PROT_LEVEL.GT.1) RETURN
+
+	CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD,GROUP)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FOLDER_TO_NEWS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	NEWS_FOLDER = FOLDER
+	NEWS_FOLDER_NUMBER = FOLDER_NUMBER
+	NEWS_FOLDER_DESCRIP = FOLDER_DESCRIP(
+     &			       MIN(45,INDEX(FOLDER_DESCRIP,' ')):)
+	NEWS_F_NBULL = F_NBULL
+	NEWS_F_COUNT = F_COUNT
+	NEWS_F_START = F_START
+	NEWS_F_LAST = F_LAST
+	NEWS_F_NEWEST_BTIM(1) = F_NEWEST_BTIM(1)
+	NEWS_F_NEWEST_BTIM(2) = F_NEWEST_BTIM(2)
+	NEWS_F_FLAG = FOLDER_FLAG
+	NEWS_F_EXPIRE = FOLDER_BBEXPIRE
+ 	NEWS_F_EXPIRE_LIMIT = F_EXPIRE_LIMIT
+
+	RETURN
+
+	ENTRY FOLDER1_TO_NEWS
+
+	NEWS_FOLDER1 = FOLDER1
+	NEWS_FOLDER1_NUMBER = FOLDER1_NUMBER
+	NEWS_FOLDER1_DESCRIP = FOLDER1_DESCRIP(
+     &			       MIN(45,INDEX(FOLDER1_DESCRIP,' ')):)
+	NEWS_F1_NBULL = F1_NBULL
+	NEWS_F1_COUNT = F1_COUNT
+	NEWS_F1_START = F1_START
+	NEWS_F1_LAST = F1_LAST
+	NEWS_F1_NEWEST_BTIM(1) = F1_NEWEST_BTIM(1)
+	NEWS_F1_NEWEST_BTIM(2) = F1_NEWEST_BTIM(2)
+	NEWS_F1_FLAG = FOLDER1_FLAG
+	NEWS_F1_EXPIRE = FOLDER1_BBEXPIRE
+	NEWS_F1_EXPIRE_LIMIT = F1_EXPIRE_LIMIT
+
+	RETURN
+
+	ENTRY NEWS_TO_FOLDER
+
+	FOLDER = NEWS_FOLDER
+	FOLDER_NUMBER = NEWS_FOLDER_NUMBER
+	FOLDER_DESCRIP = NEWS_FOLDER(:MAX(1,TRIM(NEWS_FOLDER)))
+     &			 //NEWS_FOLDER_DESCRIP
+	FOLDER_BBOARD = '::'
+	F_NBULL = NEWS_F_NBULL
+	F_COUNT = NEWS_F_COUNT
+	F_START = NEWS_F_START
+	F_LAST = NEWS_F_LAST
+	F_NEWEST_BTIM(1) = NEWS_F_NEWEST_BTIM(1)
+	F_NEWEST_BTIM(2) = NEWS_F_NEWEST_BTIM(2)
+	FOLDER_FLAG = NEWS_F_FLAG
+	IF (BTEST(FOLDER_FLAG,8)) FOLDER_BBOARD = 'NONE'
+	FOLDER_BBEXPIRE = NEWS_F_EXPIRE
+	F_EXPIRE_LIMIT = NEWS_F_EXPIRE_LIMIT
+
+	RETURN
+
+	ENTRY NEWS_TO_FOLDER1
+
+	FOLDER1 = NEWS_FOLDER1
+	FOLDER1_NUMBER = NEWS_FOLDER1_NUMBER
+	FOLDER1_DESCRIP = NEWS_FOLDER1(:MAX(1,TRIM(NEWS_FOLDER1)))
+     &			 //NEWS_FOLDER1_DESCRIP
+	FOLDER1_BBOARD = '::'
+	F1_COUNT = NEWS_F1_COUNT
+	F1_NBULL = NEWS_F1_NBULL
+	F1_START = NEWS_F1_START
+	F1_LAST = NEWS_F1_LAST
+	F1_NEWEST_BTIM(1) = NEWS_F1_NEWEST_BTIM(1)
+	F1_NEWEST_BTIM(2) = NEWS_F1_NEWEST_BTIM(2)
+	FOLDER1_FLAG = NEWS_F1_FLAG
+	IF (BTEST(FOLDER1_FLAG,8)) FOLDER1_BBOARD = 'NONE'
+	FOLDER1_BBEXPIRE = NEWS_F1_EXPIRE
+	F1_EXPIRE_LIMIT = NEWS_F1_EXPIRE_LIMIT
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE CONVERT_BULLNEWSDIR
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($FORIOSDEF)'
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+  
+	CHARACTER*180 TEMP
+
+	CHARACTER BUFFER*12,DATETIME*24
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	CALL SET_PROTECTION
+
+	CALL OPEN_BULLNEWS
+
+	OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	        STATUS='OLD',FORM='UNFORMATTED',
+     &	        RECORDTYPE='FIXED',RECORDSIZE=180/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        BUFFERCOUNT=127,KEY=(13:20:CHARACTER,
+     &	        1:8:CHARACTER,9:20:CHARACTER,21:84:CHARACTER,
+     &	        85:96:CHARACTER),ACCESS='KEYED')
+
+	IF (IER.NE.0) GO TO 900	! No BULLDIR file found.
+
+	IER1 = LIB$CREATE_DIR(
+     &		FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWSDIR]')
+	IF (.NOT.IER1) GO TO 900
+
+	NEW_FOLDER_NUMBER = 0
+
+	DO WHILE (IER.EQ.0)
+	   READ (2,IOSTAT=IER) TEMP
+	   IF (GET_INTEGER(%REF(TEMP)).NE.NEW_FOLDER_NUMBER) THEN
+	      IF (NEW_FOLDER_NUMBER.NE.0) CLOSE (UNIT=9,DISPOSE='KEEP')
+	      NEW_FOLDER_NUMBER = GET_INTEGER(%REF(TEMP))
+	      CALL SET_BULLNEWSDIR_FILE(NEW_FOLDER_NUMBER)
+              OPEN (UNIT=9,FILE=BULLNEWSDIR_FILE,
+     &	        STATUS='UNKNOWN',FORM='UNFORMATTED',SHARED,
+     &	        RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	        BUFFERCOUNT=127,
+     &	        KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	        57:64:CHARACTER),ACCESS='KEYED')
+	      IF (IER.NE.0) GO TO 900
+	   END IF
+	   NEWS_MSG_NUM = GET_INTEGER(%REF(TEMP(5:)))
+ 	   NEWS_MSG_BTIM_KEY = TEMP(13:)
+	   NEWS_EX_BTIM_KEY = TEMP(89:)
+	   NEWS_MSGID = TEMP(21:)
+ 	   CALL COPY2(MSG_BTIM,%REF(TEMP(97:)))
+	   CALL CONVERT_TO_GMT(MSG_BTIM)
+ 	   CALL GET_MSGKEY(MSG_BTIM,NEWS_POST_KEY)
+	   CALL LIB$MOVC3(76,%REF(TEMP(105:)),NEWS_BLOCK)
+
+	   WRITE (9,IOSTAT=IER1) NEWSDIR_ENTRY
+	END DO
+
+	CLOSE (UNIT=9,DISPOSE='KEEP')
+	CLOSE (UNIT=2)
+
+	CALL RESET_PROTECTION
+
+	BULLNEWSDIR_FILE = 'BULLNEWSDIR.DAT'
+	CALL ADD_DIRECTORY(BULLNEWSDIR_FILE)
+
+	IER = LIB$RENAME_FILE(BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))
+     &		,'BULLNEWSDIR.OLD')
+
+	WRITE (6,'('' BULLNEWSDIR.DAT has been renamed to '',
+     &		'' BULLNEWSDIR.OLD and may now be deleted.'')')
+
+	RETURN
+
+900	CALL RESET_PROTECTION
+
+	CALL CLOSE_BULLNEWS
+
+	WRITE(6,'('' ERROR: Cannot convert BULLNEWSDIR.DAT'')')
+	IF (IER.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	IF (IER1.EQ.0) THEN
+	   WRITE (6,'('' IOSTAT error = '',I)') IER
+	ELSE
+	   CALL SYS_GETMSG(IER1)
+	END IF
+	CALL ENABLE_CTRL_EXIT
+
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLDIRS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER BUFFER*116
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	CALL SET_PROTECTION
+
+	OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',ACCESS='DIRECT',
+     &	      ORGANIZATION='RELATIVE',DISPOSE='KEEP',
+     &	      IOSTAT=IER)
+
+	IF (IER.NE.0) GO TO 900	! No BULLDIR file found.
+
+	READ (2'1,IOSTAT=IER1) BUFFER(:115)
+
+	CALL LIB$MOVC3(4,%REF(BUFFER(39:)),NBULL)
+
+	OPEN (UNIT=9,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED',
+     &	      INITIALSIZE=(((NBULL+1)*DIR_RECORD_LENGTH)/512)+5 )
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=9,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	END IF
+
+	IF (IER1.NE.0) GO TO 800
+
+	CALL SYS_BINTIM(BUFFER(:11)//' '//BUFFER(12:19),NEWEST_EXBTIM)
+	CALL SYS_BINTIM(BUFFER(20:30)//' '//BUFFER(31:38),NEWEST_MSGBTIM)
+	BULLDIR_HEADER(29:40) = BUFFER(39:)
+	CALL SYS_BINTIM(BUFFER(51:61)//' '//BUFFER(62:69),SHUTDOWN_BTIM)
+	BULLDIR_HEADER(49:52) = BUFFER(70:)
+	IF (IER.EQ.0) WRITE (9,IOSTAT=IER) BULLDIR_HEADER
+
+	ICOUNT = 2
+	DO WHILE (IER.EQ.0)
+	   READ (2'ICOUNT,IOSTAT=IER) BUFFER(:115)
+	   IF (IER.EQ.0) THEN
+	      MSG_NUM = ICOUNT - 1
+	      DESCRIP = BUFFER(:)
+	      FROM = BUFFER(54:)
+	      BULLDIR_ENTRY(81:84) = BUFFER(85:)
+	      BULLDIR_ENTRY(93:100) = BUFFER(108:)
+	      CALL SYS_BINTIM(BUFFER(89:99)//' '//BUFFER(100:107),EX_BTIM)
+	      CALL SYS_BINTIM(BUFFER(66:76)//' '//BUFFER(77:84),MSG_BTIM)
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      WRITE (9,IOSTAT=IER) BULLDIR_ENTRY
+	      ICOUNT = ICOUNT + 1
+	   END IF
+	END DO
+
+800	CLOSE (UNIT=9,DISPOSE='KEEP')
+	CLOSE (UNIT=2)
+
+900	CALL RESET_PROTECTION
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLFILES
+C
+C  SUBROUTINE CONVERT_BULLFILES
+C
+C  FUNCTION: Converts bulletin files to new format file.
+C	Add expiration time to directory file, add extra byte to bulletin
+C	file to show where each bulletin starts (for redunancy sake in
+C	case crash occurs).
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*81 BUFFER
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	OPEN (UNIT=9,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=107,ACCESS='DIRECT',
+     &	      ORGANIZATION='RELATIVE',DISPOSE='KEEP',FORM='FORMATTED',
+     &	      SHARED,READONLY,IOSTAT=IER)
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	OPEN (UNIT=10,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='OLD',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=80,
+     &	      FORM='FORMATTED',IOSTAT=IER,SHARED,READONLY)
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	CALL SET_PROTECTION
+
+	OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='NEW',IOSTAT=IER,
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=81,
+     &	      FORM='FORMATTED')
+
+	OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+
+	NEWEST_EXTIME = '00:00:00.00'
+	READ (9'1,1000,IOSTAT=IER) 
+     &		NEWEST_EXDATE,NEWEST_DATE,NEWEST_TIME(:8),
+     &		NBULL,NBLOCK,SHUTDOWN,SHUTDOWN_DATE,SHUTDOWN_TIME(:8)
+	NEMPTY = 0
+	IF (IER.EQ.0) CALL WRITEDIR(0,IER1)
+
+	EXTIME = '00:00:00.00'
+	ICOUNT = 2
+	DO WHILE (IER.EQ.0)
+	   READ(9'ICOUNT,1010,IOSTAT=IER)
+     &		DESCRIP,FROM,DATE,TIME(:8),LENGTH,EXDATE,SYSTEM,BLOCK
+	   IF (IER.EQ.0) THEN
+	      READ(10,'(A)') BUFFER
+	      WRITE(1,'(A)') BUFFER(:80)//CHAR(1)
+	      DO I=2,LENGTH
+	         READ(10,'(A)') BUFFER
+	         WRITE(1,'(A)') BUFFER
+	      END DO
+	      CALL WRITEDIR(ICOUNT-1,IER1)
+	      ICOUNT = ICOUNT + 1
+	   END IF
+	END DO
+
+	CLOSE (UNIT=9)
+	CLOSE (UNIT=2)
+	CLOSE (UNIT=10)
+	CLOSE (UNIT=1)
+
+	CALL RESET_PROTECTION
+	RETURN
+
+1000	FORMAT(A11,A11,A8,A4,A4,A4,A11,A8)
+1010	FORMAT(A53,A12,A11,A8,A4,A11,A4,A4)
+
+	END
+
+	SUBROUTINE CONVERT_BULLFILE
+C
+C  SUBROUTINE CONVERT_BULLFILE
+C
+C  FUNCTION: Converts bulletin data file to new format file.
+C
+C  NOTE: CONVERT_BULLFILES converts from 80 to 81 byte length.
+C	 This converts from 81 byte length to 128 compressed format.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*80 BUFFER,NEW_FILE
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	CALL CLOSE_BULLDIR
+
+	CALL SET_PROTECTION
+
+	CALL OPEN_BULLFOLDER
+
+100	READ (7,FMT=FOLDER_FMT,ERR=200)
+     &		FOLDER,FOLDER_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+
+	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//FOLDER(:TRIM(FOLDER))
+	NEW_FILE = FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFILOLD'
+	OPEN (UNIT=10,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL'
+     &	      ,STATUS='OLD',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=81,ACCESS='DIRECT',
+     &	      FORM='FORMATTED',IOSTAT=IER,SHARED,READONLY)
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	   //'.BULLFIL',STATUS='NEW',IOSTAT=IER,
+     &	   ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	   FORM='UNFORMATTED')
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &		//'.BULLFIL;-1',NEW_FILE)
+
+	CALL OPEN_BULLDIR
+
+	CALL READDIR(0,IER)
+
+	IF (IER.EQ.1) THEN
+	 NBLOCK = 0
+	 DO I=1,NBULL
+	   CALL READDIR(I,IER)
+	   NBLOCK = NBLOCK + 1
+	   SBLOCK = NBLOCK
+	   DO J=BLOCK,LENGTH+BLOCK-1
+	      READ(10'J,'(A)') BUFFER
+	      ILEN = TRIM(BUFFER)
+	      IF (ILEN.EQ.0) ILEN = 1
+	      CALL STORE_BULL(ILEN,BUFFER,NBLOCK)
+	   END DO
+	   CALL FLUSH_BULL(NBLOCK)
+	   LENGTH = NBLOCK - SBLOCK + 1
+	   BLOCK = SBLOCK
+	   CALL WRITEDIR(I,IER)
+	 END DO
+
+	 NEMPTY = 0
+	 CALL WRITEDIR(0,IER)
+	END IF
+
+	CLOSE (UNIT=10)
+	CLOSE (UNIT=1)
+
+	CALL CLOSE_BULLDIR
+	GOTO 100
+
+200	CALL OPEN_BULLDIR_SHARED
+
+	CALL RESET_PROTECTION
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLFOLDER(FILENAME)
+C
+C  SUBROUTINE CONVERT_BULLFOLDER
+C
+C  FUNCTION: Converts bulletin folder file to new format.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($FORIOSDEF)'
+
+	CHARACTER*(*) FILENAME
+
+	CHARACTER NEW_FILE*80,OLD_FOLDER*25
+
+	WRITE (6,'('' Converting '',A,'' to new format. Please wait.'')')
+     &			FILENAME(:TRIM(FILENAME))
+
+	CALL SET_PROTECTION
+
+	EODIR = MAX(INDEX(FILENAME,':'),INDEX(FILENAME,']'))
+	SUFFIX = INDEX(FILENAME(EODIR:),'.') + EODIR - 1
+	NEW_FILE = FILENAME(:SUFFIX)//'OLD'
+
+	DO WHILE (FILE_LOCK(IER,IER1))
+	   OPEN (UNIT=7,FILE=FILENAME,STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:25:CHARACTER,26:29:INTEGER))
+	END DO
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	INQUIRE(UNIT=7,RECORDSIZE=ASK_SIZE)
+
+	OPEN (UNIT=19,FILE=NEW_FILE,STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=FOLDER_RECORD,
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER),
+     &		DISPOSE='DELETE')
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	IF (ASK_SIZE.EQ.184.OR.ASK_SIZE.EQ.173) THEN
+	 F_NUMBER = 0
+	 DO WHILE (IER.EQ.0)
+	   IF (ASK_SIZE.EQ.184) THEN
+	      READ (7,FMT='(A25,A4,A12,A80,A12,3A4,A8,5A4)',
+     &			KEYGE=F_NUMBER,KEYID=1,IOSTAT=IER)
+     &		OLD_FOLDER,F_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,FOLDER_SET
+	      CALL COPY2(F_NEWEST_NOSYS_BTIM,F_NEWEST_BTIM)
+	   ELSE IF (ASK_SIZE.EQ.173) THEN
+	      READ (7,FMT='(A25,A4,A12,A80,A12,3A4,A8,7A4)',
+     &			KEYGE=F_NUMBER,KEYID=1,IOSTAT=IER)
+     &		OLD_FOLDER,F_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,FOLDER_SET
+     &	        ,F_NEWEST_NOSYS_BTIM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      FOLDER = OLD_FOLDER
+	      CALL SYS_BINTIM('5-NOV-1982',NEWS_F_NEWEST_BTIM)
+              CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,FOLDER_CREATED_DATE)
+	      IF (NEWS_FEED()) THEN 
+		 CALL LIB$MOVC3(4,%REF(FOLDER_BBOARD(7:)),F_LAST)
+	      ELSE
+	         F_LAST = 0
+	      END IF
+	      WRITE (19,FMT=FOLDER_FMT,IOSTAT=IER)
+     &	        FOLDER,F_NUMBER,FOLDER_CREATED_DATE
+     &		,FOLDER_OWNER,FOLDER_DESCRIP
+     &	        ,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,FOLDER_SET
+     &		,F_NEWEST_NOSYS_BTIM,0,0,F_LAST
+	      F_NUMBER = F_NUMBER + 1
+	   END IF
+	 END DO
+	ELSE
+	 F_NUMBER = 0
+	 DO WHILE (IER.EQ.0)
+	   READ (7,FMT='(A25,A4,A12,A80,A12,3A4,A8)',
+     &			KEYGE=F_NUMBER,KEYID=1,IOSTAT=IER)
+     &		OLD_FOLDER,F_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+	   IF (IER.EQ.0) THEN
+	      FOLDER_FLAG = 0
+	      IF (F_NUMBER.EQ.0) FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	      FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//OLD_FOLDER(:TRIM(OLD_FOLDER))
+	      CALL CHKACL
+     &		(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',IER)
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.IER) THEN
+		 FOLDER_FLAG = IBSET(FOLDER_FLAG,0)
+	      END IF
+	      DO WHILE (FILE_LOCK(IER,IER1))
+	       OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	         //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	         RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	         ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	         KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	        IF (IER.EQ.FOR$IOS_INCFILORG) THEN
+	          IDUMMY = FILE_LOCK(IER,IER1)
+	          CALL CONVERT_BULLDIRS
+		END IF
+	      END DO
+	      IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+		 F_NEWEST_BTIM(1) = 0
+		 F_NEWEST_BTIM(2) = 0
+	      ELSE
+	         CALL READDIR(0,IER)
+	         IF (NEWEST_DATE.EQ.'5-NOV-1956 ') THEN
+		    IF (NBULL.GT.0) THEN
+		       CALL READDIR(NBULL,IER)
+		       NEWEST_DATE = DATE
+		       NEWEST_TIME = TIME
+		       CALL WRITEDIR(0,IER)
+		    END IF
+	         END IF
+	         CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,F_NEWEST_BTIM)
+	         CLOSE (UNIT=2)
+	      END IF
+	      FOLDER = OLD_FOLDER
+              CALL SYS_BINTIM('5-NOV-1982',NEWS_F_NEWEST_BTIM)
+              CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,FOLDER_CREATED_DATE)
+              WRITE (19,FMT=FOLDER_FMT,IOSTAT=IER)
+     &          FOLDER,F_NUMBER,FOLDER_CREATED_DATE
+     &	       ,FOLDER_OWNER,FOLDER_DESCRIP
+     &	        ,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,NBULL,F_NEWEST_BTIM,FOLDER_FLAG,0,F_NEWEST_BTIM,0,0,0
+	      F_NUMBER = F_NUMBER + 1
+	   END IF
+	 END DO
+	END IF
+
+	CLOSE (UNIT=7)
+	CLOSE (UNIT=19,STATUS='SAVE')
+
+	IER = LIB$RENAME_FILE(NEW_FILE,FILENAME)
+	IER = LIB$RENAME_FILE(BULLFOLDER_FILE//';-1',NEW_FILE)
+
+	CALL RESET_PROTECTION
+
+	IER = LIB$DELETE_FILE(BBOARD_DIRECTORY(:TRIM(BBOARD_DIRECTORY))
+     &		//'BOARD.COM;*')	! BULLETIN$ is referenced in old file
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLNEWS(FILENAME)
+C
+C  SUBROUTINE CONVERT_BULLNEWS
+C
+C  FUNCTION: Converts bulletin NEWS file to new format.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($FORIOSDEF)'
+
+	CHARACTER*(*) FILENAME
+
+	CHARACTER NEW_FILE*80,OLD_FOLDER*25,OLD_DESCRIP*55,TMP*2     
+
+	WRITE (6,'('' Converting '',A,'' to new format. ''
+     &		,''This will take a while.'')') FILENAME(:TRIM(FILENAME))
+
+	CALL SET_PROTECTION
+
+	EODIR = MAX(INDEX(FILENAME,':'),INDEX(FILENAME,']'))
+	SUFFIX = INDEX(FILENAME(EODIR:),'.') + EODIR - 1
+	NEW_FILE = FILENAME(:SUFFIX)//'OLD'
+
+	DO WHILE (FILE_LOCK(IER,IER1))
+	   OPEN (UNIT=7,FILE=FILENAME,STATUS='OLD',
+     &	        RECORDTYPE='FIXED',ACCESS='KEYED',
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:25:CHARACTER,26:29:INTEGER))
+	END DO
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	OPEN (UNIT=19,FILE=NEW_FILE,STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD/4,INITIALSIZE=600,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER,
+     &		57:64:CHARACTER:DESCENDING),DISPOSE='DELETE')
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	NEWS_FOLDER_NUMBER = 0
+        CALL SYS_BINTIM('5-NOV-1982',NEWS_F_NEWEST_BTIM)
+        CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,NEWS_F_CREATED_DATE)
+        CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NEWS_F_NEWEST_BTIM)
+        CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,NEWS_F_EXPIRED_DATE)
+	NEWS_F_LAST = 0
+	NEWS_F_FLAG = 0
+	NEWS_F_EXPIRE = 7
+	NEWS_F_FIRST = 0
+	NEWS_F_END = 0
+	NEWS_F_EXPIRE_LIMIT = 0
+	READ (7,KEY=1000,KEYID=1,IOSTAT=IER) INPUT(:108)
+	DO WHILE (IER.EQ.0)
+	      OLD_FOLDER = INPUT(:25)
+	      CALL LIB$MOVC3(4,%REF(INPUT(26:)),NEWS_FOLDER_NUMBER)
+	      OLD_DESCRIP = INPUT(30:)
+	      CALL LIB$MOVC3(4,%REF(INPUT(87:)),NEWS_F_START)
+              CALL LIB$MOVC3(4,%REF(INPUT(91:)),NEWS_F_COUNT)
+              CALL LIB$MOVC3(4,%REF(INPUT(97:)),NEWS_F_NBULL)
+              CALL LIB$MOVC3(8,%REF(INPUT(101:)),NEWS_F_NEWEST_BTIM)
+	      LMOVE = INDEX(OLD_DESCRIP,' ')-1
+	      IF (LMOVE.LE.0) THEN
+	         NEWS_FOLDER = OLD_FOLDER
+	         NEWS_FOLDER_DESCRIP = OLD_DESCRIP
+	      ELSE
+	         NEWS_FOLDER = OLD_FOLDER//OLD_DESCRIP(:MIN(19,LMOVE))
+	         NEWS_FOLDER_DESCRIP = OLD_DESCRIP(MIN(20,LMOVE+1):)
+	      END IF
+  	      WRITE (19,IOSTAT=IER) NEWS_FOLDER_COM  
+	      READ (7,IOSTAT=IER) INPUT(:108)
+	 END DO
+
+	CLOSE (UNIT=7)
+	CLOSE (UNIT=19,STATUS='SAVE')
+
+	IER = LIB$RENAME_FILE(NEW_FILE,FILENAME)
+	IER = LIB$RENAME_FILE(BULLNEWS_FILE//';-1',NEW_FILE)
+
+	CALL RESET_PROTECTION
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_USERFILE
+C
+C  SUBROUTINE CONVERT_USERFILE
+C
+C  FUNCTION: Converts user file to new format which has 8 bytes added.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER BUFFER*74,NEW_FILE*80
+
+	CHARACTER*12 LOGIN_DATE,READ_DATE
+	CHARACTER*8 LOGIN_TIME,READ_TIME
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	EODIR = MAX(INDEX(BULLUSER_FILE,':'),INDEX(BULLUSER_FILE,']'))
+	SUFFIX = INDEX(BULLUSER_FILE(EODIR:),'.') + EODIR - 1
+	NEW_FILE = BULLUSER_FILE(:SUFFIX)//'OLD'
+	IER = LIB$RENAME_FILE(BULLUSER_FILE,NEW_FILE)
+
+	OPEN (UNIT=9,FILE=NEW_FILE,STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	     FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	     KEY=(1:12:CHARACTER))
+	INQUIRE (UNIT=9,RECORDSIZE=RECL)
+
+	IF ((RECL-28)/16.GT.FLONG) THEN
+	   WRITE (6,'('' ERROR: Old data files have more folders'',
+     &		      '' than was specified with BULLUSER.INC.'')')
+	   WRITE (6,'('' Recompile with correct FOLDER_MAX.'')')
+	   IER = LIB$RENAME_FILE(NEW_FILE,BULLUSER_FILE)
+	   IF (USERNAME.EQ.'DECNET') THEN
+	      CALL SYS$DELPRC(,)
+	   ELSE
+	      CALL ENABLE_CTRL
+	      CALL SYS$CANEXH()
+	      CALL EXIT
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   CALL SET_PROTECTION
+	   OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='NEW',
+     &	    ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=28+FLONG*16,
+     &	    FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	    KEY=(1:12:CHARACTER))
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' Cannot convert user file.'')')
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   CALL SYS_GETMSG(IER1)
+	   CALL RESET_PROTECTION
+	   CALL ENABLE_CTRL_EXIT
+	END IF
+
+	DO I=1,FLONG
+	   NEW_FLAG(I) = 'FFFFFFFF'X
+	   NOTIFY_FLAG(I) = 0
+	   BRIEF_FLAG(I) = 0
+	   SET_FLAG(I) = 0
+	END DO
+
+	IF (RECL.EQ.42.OR.RECL.EQ.50.OR.RECL.EQ.58.OR.RECL.EQ.66.OR.
+     &		RECL.EQ.74) THEN		! Old format
+	   IF (RECL.LE.58) RECL = 50
+	   IER = 0
+	   DO WHILE (IER.EQ.0)
+	      READ (9,'(A<RECL>)',IOSTAT=IER) BUFFER
+	      IF (IER.EQ.0) THEN
+		TEMP_USER = BUFFER(:12)
+	        LOGIN_DATE = BUFFER(13:23)
+	        LOGIN_TIME = BUFFER(24:31)
+	        READ_DATE = BUFFER(32:42)
+	        READ_TIME = BUFFER(43:50)
+	        IF (RECL.EQ.58)
+     &		  CALL LIB$MOVC3(8,%REF(BUFFER(51:)),SET_FLAG(1))
+	        IF (RECL.EQ.66)
+     &		  CALL LIB$MOVC3(8,%REF(BUFFER(59:)),NEW_FLAG(1))
+	        IF (RECL.EQ.74)
+     &		  CALL LIB$MOVC3(8,%REF(BUFFER(67:)),NOTIFY_FLAG(1))
+	        CALL SYS_BINTIM(LOGIN_DATE//' '//LOGIN_TIME,LOGIN_BTIM)
+	        CALL SYS_BINTIM(READ_DATE//' '//READ_TIME,READ_BTIM)
+	        WRITE (4,FMT=USER_FMT) TEMP_USER,LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	    END IF
+	   END DO
+	   IF (RECL.LT.66) THEN
+	     READ (4,KEY=USER_HEADER_KEY,FMT=USER_FMT) TEMP_USER,
+     &		LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	     NEW_FLAG(1) = PRV$M_OPER.OR.PRV$M_CMKRNL.OR.PRV$M_SETPRV
+	     WRITE (4,FMT=USER_FMT) TEMP_USER,LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	   END IF
+	ELSE					! Folder maxmimum increase
+	   OFLONG = (RECL - 28) / 16		! Old  #longwords/flag
+	   DO WHILE (IER.EQ.0)
+	    READ (9,FMT='(A12,<4+OFLONG*4>A4)',IOSTAT=IER) 
+     &	     TEMP_USER,LOGIN_BTIM,READ_BTIM,
+     &	     (NEW_FLAG(I),I=1,OFLONG),(SET_FLAG(I),I=1,OFLONG),
+     &	     (BRIEF_FLAG(I),I=1,OFLONG),(NOTIFY_FLAG(I),I=1,OFLONG)
+	    IF (IER.EQ.0) THEN
+	     WRITE (4,FMT=USER_FMT) TEMP_USER,LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	    END IF
+	   END DO
+	END IF
+
+	IER = 0
+
+	CLOSE (UNIT=9)
+	CLOSE (UNIT=4)
+
+	CALL RESET_PROTECTION
+
+	RETURN
+	END
+
+
+	SUBROUTINE READDIR(BULLETIN_NUM,ICOUNT)
+C
+C  SUBROUTINE READDIR
+C
+C  FUNCTION: Finds the entry for the specified bulletin in the
+C	directory file and returns the information for that entry.
+C
+C  INPUTS:
+C	BULLETIN_NUM  -  Bulletin number.  Starts with 1.
+C			 If 0, gives header info, i.e number of bulls,
+C			 number of blocks in bulletin file, etc.
+C  OUTPUTS:
+C	ICOUNT  -  The last record read by this routine.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /KEEPLOCK/ KEEPLOCK
+	DATA KEEPLOCK/.FALSE./
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /BULLFIL/ BULLFIL
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /THREAD/ THREAD
+
+	CHARACTER*4 CFOLDER_NUMBER
+
+	ICOUNT = BULLETIN_NUM
+
+	IF (ICOUNT.EQ.0) THEN
+	   IF (.NOT.REMOTE_SET) THEN
+	      DO WHILE (REC_LOCK(IER))
+		IF (REMOTE_SET.EQ.4) THEN
+		   IER = 0
+		ELSE
+	           READ (2,KEYID=0,KEY=0,IOSTAT=IER) BULLDIR_HEADER
+		END IF
+	      END DO
+	      IF (IER.EQ.0) THEN
+		 CALL CONVERT_HEADER_FROMBIN
+		 IF (REMOTE_SET.EQ.4) THEN
+		    DIR_NUM = -1
+		 ELSE
+	            DIR_NUM = 0
+		 END IF
+	      END IF
+	   ELSE
+	      CALL REMOTE_GET_HEADER(BULLETIN_NUM,ICOUNT,IER)
+	      RETURN
+	   END IF
+	   IF (IER.EQ.0.AND..NOT.REMOTE_SET.EQ.4) THEN
+	      IF (NBULL.LT.0) THEN	! This indicates bulletin deletion
+					! was incomplete.
+		 CALL CLOSE_BULLDIR
+		 CALL OPEN_BULLDIR
+		 CALL CLEANUP_DIRFILE(1)
+		 CALL UPDATE_FOLDER
+	      END IF
+	      IF (NEMPTY.EQ.'    '.AND.
+     &		  FOLDER_BBOARD(:2).NE.'::') NEMPTY = 0
+C
+C  Check to see if cleanup of empty file space is necessary, which is
+C  defined here as being 250 blocks (1000 128byte records).  Also check
+C  to see if cleanup was in progress but didn't properly finish.
+C
+	      IF (NEMPTY.GT.1000.AND.NEMPTY.GT.NBLOCK/10
+     &		  .AND.TEST_BULLCP().EQ.0) THEN
+		 WRITE (CFOLDER_NUMBER,'(I4)') FOLDER_NUMBER
+	         IER1 = LIB$SPAWN('$'//COMMAND_PROMPT(:INDEX(
+     &		  COMMAND_PROMPT,'>')-1)//'/CLEANUP='//CFOLDER_NUMBER,
+     &		  'NL:','NL:',1,'BULL_CLEANUP')
+	      ELSE IF (NEMPTY.EQ.-1) THEN
+		 CALL CLOSE_BULLDIR
+		 CALL CLOSE_BULLFIL
+		 CALL OPEN_BULLDIR
+	         IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &			//'.TMPFIL','*.BULLFIL')
+	         IER = 1
+		 DO WHILE (IER)
+	    	   IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &				//'.BULLFIL;-1')
+		 END DO
+	         IER = 1
+		 DO WHILE (IER)
+	    	   IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &				//'.BULLDIR;-1')
+		 END DO
+		 IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &			'.BULL*','*.*;1')
+	         READ (2,KEYID=0,KEY=0,IOSTAT=IER) BULLDIR_HEADER
+		 NEMPTY = 0
+	         REWRITE (2,IOSTAT=IER) BULLDIR_HEADER
+	         READ (2,KEYID=0,KEY=0,IOSTAT=IER) BULLDIR_HEADER
+		 CALL OPEN_BULLFIL
+	      END IF
+	   END IF
+	ELSE
+	   IF (.NOT.REMOTE_SET) THEN
+	      DO WHILE (REC_LOCK(IER))
+		 IF (REMOTE_SET.EQ.4) THEN
+		    IF (NEXT) THEN
+		       IF (DIR_NUM.EQ.ICOUNT-1) THEN
+	                  READ(2,IOSTAT=IER) NEWSDIR_ENTRY
+	               ELSE
+	                  READ(2,KEYGE=ICOUNT
+     &			    ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY
+	               END IF
+		    ELSE
+		       IF (ICOUNT.LT.F_START) ICOUNT = F_START
+		       IF (ICOUNT.GT.F_NBULL) ICOUNT = F_NBULL
+	               IF (DIR_NUM.EQ.ICOUNT-1) THEN
+			  READ(2,IOSTAT=IER) NEWSDIR_ENTRY
+                       ELSE
+	                  READ(2,KEY=ICOUNT
+     &			    ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY
+			  IF (IER.NE.0.AND.ICOUNT.EQ.F_START) THEN
+	                     READ(2,KEYGT=ICOUNT
+     &			          ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY
+			     IF (IER.EQ.0) ICOUNT = NEWS_MSG_NUM
+			  END IF
+		       END IF
+		       IF (INCMD(:4).EQ.'BACK') THEN
+		          DO WHILE (IER.NE.0.AND.ICOUNT.GT.F_START)
+	                     ICOUNT = ICOUNT - 1
+			     READ(2,KEY=ICOUNT
+     &		                     ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY 
+                          END DO
+		       END IF
+		    END IF
+		    IF (IER.EQ.0) THEN
+			  MSG_NUM = NEWS_MSG_NUM
+			  IF (MSG_NUM.GT.F_NBULL) THEN 
+			     IER = 36 
+			     UNLOCK 2
+                          ELSE IF (ICOUNT.LE.F_START.AND.
+     &				 MSG_NUM.GT.F_START) THEN
+			     INQUIRE (UNIT=7,OPENED=IER1)
+			     IF (.NOT.IER1) CALL OPEN_BULLNEWS_SHARED
+			     IDUMMY = REC_LOCK(IER)
+			     CALL READ_FOLDER_FILE_KEYNAME
+     &							(FOLDER,IER2)
+			     F_START = MSG_NUM
+		             CALL REWRITE_FOLDER_FILE(IER2)
+			     IF (.NOT.IER1) CALL CLOSE_BULLNEWS
+			     IDUMMY = REC_LOCK(IER)
+	                  END IF
+		       IF (IER.EQ.0.AND.MSG_NUM.NE.BULLETIN_NUM) THEN
+			  ICOUNT = MSG_NUM
+			  BULLETIN_NUM = ICOUNT
+		       END IF
+		    END IF
+		 ELSE
+                    IF (DIR_NUM.EQ.ICOUNT-1) THEN
+	               READ(2,IOSTAT=IER) BULLDIR_ENTRY
+		       IF (IER.EQ.0.AND.BLOCK.EQ.0) THEN
+			  REWRITE (2) BULLDIR_ENTRY(:65)//'   '//
+     &					BULLDIR_ENTRY(66:97)
+	                  READ(2,KEYID=0,KEY=ICOUNT,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		       END IF
+		       IF (MSG_NUM.NE.ICOUNT) THEN
+		          IER = 36
+		          UNLOCK 2 
+		       END IF
+		    ELSE
+	               READ(2,KEYID=0,KEY=ICOUNT,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		       IF (IER.EQ.0.AND.BLOCK.EQ.0) THEN
+			  REWRITE (2) BULLDIR_ENTRY(:65)//'   '//
+     &					BULLDIR_ENTRY(66:97)
+	                  READ(2,KEYID=0,KEY=ICOUNT,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		       END IF
+		    END IF
+		 END IF
+	      END DO
+	      IF (IER.EQ.0) THEN
+		 IF (REMOTE_SET.NE.4) CALL STR$UPCASE(FROM,FROM)
+	      	 CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+		 CALL CONVERT_ENTRY_FROMBIN
+		 DIR_NUM = MSG_NUM
+	         IF (REMOTE_SET.EQ.4.AND.BULLFIL.GT.0) CALL SET_BULLFIL
+	      ELSE
+		 DIR_NUM = -1
+	      END IF
+	   ELSE
+	      CALL REMOTE_GET_HEADER(BULLETIN_NUM,ICOUNT,IER)
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   IF (.NOT.REMOTE_SET) THEN
+	      ICOUNT = ICOUNT + 1
+	      IF (.NOT.KEEPLOCK) UNLOCK 2
+	   END IF
+	   IF (ICOUNT.GT.1.AND.BTEST(BULL_USER_CUSTOM,1)) THEN
+	      IF (BTEST(BULL_USER_CUSTOM,3)) THEN
+	         IF (.NOT.INCLUDE_MSG(FROM,DESCRIP)) ICOUNT = ICOUNT - 1
+	      ELSE IF (THREAD) THEN
+		 DUMMY = INCLUDE_MSG(FROM,DESCRIP)
+	      END IF
+       	   END IF
+	END IF
+
+	RETURN
+
+	END
+
+
+
+	INTEGER FUNCTION GET_INTEGER(NUM)
+
+        IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*4 CTEMP,INTEGER_KEY
+
+	CTEMP = INTEGER_KEY(NUM)
+
+	CALL LIB$MOVC3(4,%REF(CTEMP),GET_INTEGER)
+
+	RETURN
+	END
+
+
+
+	CHARACTER*4 FUNCTION INTEGER_KEY(NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER TEMP
+	CHARACTER*4 CTEMP
+	EQUIVALENCE (CTEMP,TEMP)
+
+	TEMP = NUM
+
+	DO I=4,1,-1
+	   INTEGER_KEY(I:I) = CTEMP(5-I:5-I)
+	END DO
+
+	RETURN
+	END
+
+
+	SUBROUTINE READDIR_KEYGE(IER)
+C
+C  SUBROUTINE READDIR_KEYGE
+C
+C  FUNCTION: Finds the entry for the specified bulletin in the
+C	directory file corresponding to or later than the date specified.
+C
+C  INPUTS:
+C	MSG_KEY	- Message key (passed via BULLDIR.INC common block).
+C  OUTPUTS:
+C	IER  -  If 0, no entry found.  Else contains message number.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+	COMMON /KEYID/ NEWS_KEYID
+	DATA NEWS_KEYID/1/
+
+	COMMON /KEEPLOCK/ KEEPLOCK
+
+	COMMON /BULLFIL/ BULLFIL
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+10	IF (.NOT.REMOTE_SET) THEN
+	   DO WHILE (REC_LOCK(IER))
+	      IF (REMOTE_SET.EQ.4) THEN
+	         IF (NEWS_KEYID.NE.2.OR.MSG_NUM.EQ.0) THEN
+		    READ(2,KEYGT=MSG_KEY
+     &		      ,KEYID=NEWS_KEYID,IOSTAT=IER) NEWSDIR_ENTRY
+                 ELSE
+		    READ(2,IOSTAT=IER) NEWSDIR_ENTRY
+	         END IF
+ 	         IF (IER.EQ.0) THEN
+		       MSG_NUM = NEWS_MSG_NUM
+		       IF (MSG_NUM.GT.F_NBULL) THEN
+			   IF (NEWS_KEYID.EQ.2.AND.MSG_NUM.NE.0) THEN 
+			     IF (MSG_NUM.GT.NEWS_F_END) THEN
+				IDUMMY = REC_LOCK(IER)
+			     END IF
+	                   ELSE
+		             IER = 36
+			     UNLOCK 2
+			   END IF
+	               END IF
+	         END IF
+	      ELSE
+	         READ(2,KEYID=1,KEYGT=MSG_KEY,IOSTAT=IER)
+     &					BULLDIR_ENTRY
+		 IF (IER.EQ.0.AND.BLOCK.EQ.0) THEN
+		    REWRITE (2) BULLDIR_ENTRY(:65)//'   '//
+     &					BULLDIR_ENTRY(66:97)
+	            READ(2,KEYID=0,KEY=MSG_NUM,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		 END IF
+	      END IF
+	   END DO
+	   IF (IER.EQ.0) THEN
+	      IER = MSG_NUM
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      CALL CONVERT_ENTRY_FROMBIN
+	      DIR_NUM = MSG_NUM
+	      IF (.NOT.KEEPLOCK) UNLOCK 2
+	      IF (REMOTE_SET.EQ.4.AND.BULLFIL.GT.0) CALL SET_BULLFIL
+	   ELSE
+	      IER = 0
+	      DIR_NUM = -1
+	   END IF
+	ELSE
+	   CALL REMOTE_GET_HEADER(DUMMY,-1,IER)
+ 	END IF
+
+	IF (IER.GT.0.AND.BTEST(BULL_USER_CUSTOM,1)) THEN
+	   IF (BTEST(BULL_USER_CUSTOM,3)) THEN
+	      IF (.NOT.INCLUDE_MSG(FROM,DESCRIP)) GO TO 10
+	   END IF
+       	END IF
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CONVERT_HEADER_FROMBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*24 DATETIME
+
+	IF (REMOTE_SET.EQ.4) THEN
+ 	   CALL COPY2(NEWEST_MSGBTIM,NEWS_F_NEWEST_BTIM)
+	   CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),%DESCR(NEWEST_EXBTIM))
+           NBULL = F_NBULL
+	   NEMPTY = 0
+	END IF
+
+	CALL SYS$ASCTIM(,DATETIME,NEWEST_EXBTIM,)
+
+	NEWEST_EXDATE = DATETIME(:11)
+	NEWEST_EXTIME = DATETIME(13:23)
+
+	CALL SYS$ASCTIM(,DATETIME,NEWEST_MSGBTIM,)
+
+	NEWEST_DATE = DATETIME(:11)
+	NEWEST_TIME = DATETIME(13:23)
+
+	CALL SYS$ASCTIM(,DATETIME,SHUTDOWN_BTIM,)
+
+	SHUTDOWN_DATE = DATETIME(:11)
+	SHUTDOWN_TIME = DATETIME(13:23)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_ENTRY_FROMBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /POST/ POSTTIME
+
+	CHARACTER*24 DATETIME
+
+	IF (REMOTE_SET.EQ.4) THEN
+ 	   CALL GET_MSGKEY(%REF(NEWS_MSG_BTIM_KEY),%DESCR(MSG_BTIM))
+ 	   CALL GET_MSGKEY(%REF(NEWS_EX_BTIM_KEY),%DESCR(EX_BTIM))
+	   IF (POSTTIME) THEN
+	      CALL GET_MSGKEY(%REF(NEWS_POST_KEY),%DESCR(MSG_BTIM))
+	      CALL CONVERT_FROM_GMT(MSG_BTIM)	! Assume stored is GMT
+	   END IF
+           DESCRIP = NEWS_DESCRIP
+           FROM = NEWS_FROM  
+           BLOCK = NEWS_BLOCK
+	   LENGTH = NEWS_LENGTH
+	   SYSTEM = 0
+	END IF
+
+	ENTRY CONVERT_ENTRY_FROMBIN_FOLDER 
+
+	CALL SYS$ASCTIM(,DATETIME,EX_BTIM,)
+
+	EXDATE = DATETIME(:11)
+	EXTIME = DATETIME(13:23)
+
+	CALL SYS$ASCTIM(,DATETIME,MSG_BTIM,)
+
+	DATE = DATETIME(:11)
+	TIME = DATETIME(13:23)
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE WRITEDIR(BULLETIN_NUM,IER)
+C
+C  SUBROUTINE WRITEDIR
+C
+C  FUNCTION: Writes the entry for the specified bulletin in the
+C	directory file.
+C
+C  INPUTS:
+C	BULLETIN_NUM  -  Bulletin number.  Starts with 1.
+C			 If 0, write the header of the directory file.
+C  OUTPUTS:
+C	IER - Error status from WRITE.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+	CHARACTER*52 BULLDIR_HEADER1
+
+	CONV = .TRUE.
+
+	GO TO 10
+
+	ENTRY WRITEDIR_NOCONV(BULLETIN_NUM,IER)
+
+	CONV = .FALSE.
+	
+10	IF (BULLETIN_NUM.EQ.0) THEN
+	   IF (CONV) CALL CONVERT_HEADER_TOBIN
+	   IF (REMOTE_SET) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER)9,0,BULLDIR_HEADER
+	   ELSE
+	      IER = -1
+	      IF (DIR_NUM.EQ.0) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+                    IER = 0
+		 ELSE
+	            REWRITE (2,IOSTAT=IER) BULLDIR_HEADER
+		 END IF
+	      END IF
+	      IF (IER.NE.0) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+		    IER = 0
+		 ELSE
+		    READ (2,KEYID=0,KEY=0,IOSTAT=IER) BULLDIR_HEADER1
+		    IF (IER.EQ.0) THEN 
+	               REWRITE (2,IOSTAT=IER) BULLDIR_HEADER
+		    END IF
+		 END IF
+	      END IF
+	      IF (IER.NE.0) THEN
+		 IF (REMOTE_SET.NE.4) THEN
+	            WRITE (2,IOSTAT=IER) BULLDIR_HEADER
+		 END IF
+	      END IF
+	   END IF
+	ELSE
+	   MSG_NUM = BULLETIN_NUM
+	   IF (CONV) CALL CONVERT_ENTRY_TOBIN
+	   IF (REMOTE_SET) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER)9,BULLETIN_NUM,
+     &							BULLDIR_ENTRY
+	   ELSE
+	      IER = -1
+	      IF (DIR_NUM.EQ.MSG_NUM) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+	            REWRITE (2,IOSTAT=IER) NEWSDIR_ENTRY
+		 ELSE
+	            REWRITE (2,IOSTAT=IER) BULLDIR_ENTRY
+		 END IF
+	      END IF
+	      IF (IER.NE.0) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+		    IF (BULLETIN_NUM.NE.NEWS_F_END+1) THEN
+		       DO WHILE (REC_LOCK(IER))
+	                  READ (2,KEYID=0,KEY=BULLETIN_NUM,IOSTAT=IER)
+		       END DO
+		    END IF
+		 ELSE
+	            READ (2,KEYID=0,KEY=BULLETIN_NUM,IOSTAT=IER)
+		 END IF
+		 IF (REMOTE_SET.EQ.4.AND.
+     &			BULLETIN_NUM.EQ.NEWS_F_END+1) THEN
+                    CALL SPECIAL_NEWSDIR_ENTRY(IER)
+	         ELSE IF (IER.EQ.0) THEN
+		    IF (REMOTE_SET.EQ.4) THEN
+	               REWRITE (2,IOSTAT=IER) NEWSDIR_ENTRY
+		    ELSE
+	               REWRITE (2,IOSTAT=IER) BULLDIR_ENTRY
+		    END IF
+	         ELSE
+		    IF (REMOTE_SET.EQ.4) THEN
+	               WRITE (2,IOSTAT=IER) NEWSDIR_ENTRY
+		    ELSE
+	               WRITE (2,IOSTAT=IER) BULLDIR_ENTRY
+		    END IF
+		 END IF
+	      END IF
+	   END IF
+	END IF
+
+	IF (REMOTE_SET.AND.IER.GT.0) CALL ERROR_AND_EXIT
+
+	DIR_NUM = -1
+
+	RETURN
+
+	END
+
+
+
+        SUBROUTINE SPECIAL_NEWSDIR_ENTRY(IER)
+
+        IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLDIR.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	CHARACTER*140 TEMP
+
+	DIMENSION BTIM(2)
+
+        READ (2,KEYID=3,KEY=NEWS_POST_KEY,IOSTAT=IER) TEMP
+	DO WHILE (IER.EQ.0.AND.NEWS_POST_KEY.EQ.TEMP(57:64))
+	   IF (NEWS_MSGID.EQ.TEMP(21:56)) THEN  
+	      IER = 2
+	      RETURN
+	   END IF
+           READ (2,IOSTAT=IER) TEMP
+	END DO
+
+10	IER1 = 0
+	DO WHILE (REC_LOCK(IER1))
+	   READ (2,KEYID=0,KEYGT=NEWS_F_END,
+     &			IOSTAT=IER1) INPUT(:NEWSDIR_RECORD_LENGTH)
+	END DO		
+	DO WHILE (IER1.EQ.0)
+	   CALL LIB$MOVC3(4,%REF(INPUT),FNUM)
+	   CALL GET_MSGKEY(%REF(INPUT(13:)),%DESCR(BTIM))
+	   IF (COMPARE_BTIM(BTIM,NEWEST_EXBTIM).LT.0.AND.
+     &		  .NOT.BTEST(FOLDER_FLAG,13)) THEN
+	      CALL COPY2(NEWEST_EXBTIM,BTIM)
+	   END IF
+	   F_COUNT = F_COUNT + 1
+	   CALL LIB$MOVC3(4,%REF(INPUT),NEWS_F_END)
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (2,IOSTAT=IER1) INPUT(:NEWSDIR_RECORD_LENGTH)
+	   END DO		
+	END DO
+
+	IF (MSG_NUM.NE.NEWS_F_END+1) THEN
+	   MSG_NUM = NEWS_F_END + 1
+	   CALL CONVERT_ENTRY_TOBIN
+	END IF
+	WRITE (2,IOSTAT=IER) NEWSDIR_ENTRY  
+
+	IF (IER.NE.0) THEN
+	   CALL ERRSNS(IDUMMY,IER1)
+           IF (IER1.EQ.RMS$_DUP) GO TO 10
+	ELSE
+	   F_COUNT = F_COUNT + 1
+	END IF	
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_HEADER_TOBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFOLDER.INC' 
+
+	INCLUDE 'BULLDIR.INC'
+
+        COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CALL SYS_BINTIM(NEWEST_EXDATE//' '//NEWEST_EXTIME,NEWEST_EXBTIM)
+
+	CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,NEWEST_MSGBTIM)
+
+	CALL SYS_BINTIM(SHUTDOWN_DATE//' '//SHUTDOWN_TIME,SHUTDOWN_BTIM)
+
+	IF (REMOTE_SET.EQ.4) THEN
+ 	   CALL COPY2(NEWS_F_NEWEST_BTIM,NEWEST_MSGBTIM)
+           CALL GET_MSGKEY(NEWEST_EXBTIM,NEWS_F_EXPIRED_DATE)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_ENTRY_TOBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+        COMMON /LOCALPOST/ LOCAL_POST
+
+	CALL SYS_BINTIM(EXDATE//' '//EXTIME,EX_BTIM)
+
+        IF (REMOTE_SET.EQ.4) THEN
+	   CALL CONVERT_TO_GMT(MSG_BTIM)
+	   CALL GET_MSGKEY(MSG_BTIM,NEWS_POST_KEY)
+       	   CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,MSG_BTIM)
+	ELSE
+       	   CALL SYS_BINTIM(DATE//' '//TIME,MSG_BTIM)
+        END IF
+
+	IF (LOCAL_POST) THEN
+	   CALL SYS_BINTIM(DATE//' '//TIME
+     &			   (:TRIM(TIME)-2)//'00',MSG_BTIM)
+	   CALL GET_MSGKEY(MSG_BTIM,NEWS_POST_KEY)
+	END IF
+
+	IF (REMOTE_SET.EQ.4) THEN
+           NEWS_DESCRIP = DESCRIP
+           NEWS_FROM = FROM
+           NEWS_BLOCK = BLOCK
+           NEWS_LENGTH = LENGTH
+           NEWS_MSG_NUM = MSG_NUM
+	   CALL GET_MSGKEY(MSG_BTIM,NEWS_MSG_BTIM_KEY)
+	   CALL GET_MSGKEY(EX_BTIM,NEWS_EX_BTIM_KEY)
+	ELSE
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_FIRST_EXPIRED(NDEL)
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLDIR.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+ 
+        COMMON /KEYID/ NEWS_KEYID
+
+	COMMON /KEEPLOCK/ KEEPLOCK
+ 
+	EX_BTIM(1) = 0
+	EX_BTIM(2) = 0	
+	MSG_NUM = 0
+
+	ENTRY READ_NEXT_EXPIRED(NDEL) 	
+
+	NEWS_KEYID = 2
+	KEEPLOCK = .TRUE.
+      	CALL GET_MSGKEY(EX_BTIM,MSG_KEY)
+	CALL READDIR_KEYGE(NDEL)
+	KEEPLOCK = .FALSE.
+	NEWS_KEYID = 1
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READACL(FILENAME,ACLENT,ACLLENGTH)
+C
+C  SUBROUTINE READACL
+C
+C  FUNCTION: Reads the ACL of a file.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C	ACLENT - String which will be large enough to hold ACL information.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER ACLENT*(*),OUTPUT*80,ACLSTR*256,FILENAME*(*)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_READACL,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST),,,)
+
+	BIG = .NOT.IER
+	IF (BIG) THEN
+	   IER = SYS$PARSE_ACL('(ID=*,ACCESS=NONE)',ACLENT,,)
+	   ACLLENGTH = ACL$S_ADDACLENT
+	   CTXT = 0
+	END IF
+
+	DO ACC_TYPE=1,2
+	 POINT = 1
+	 OUTLEN = 0
+	 DO WHILE ((POINT.LT.ACLLENGTH).AND.IER)
+	   IF (.NOT.BIG) THEN
+	      IER = SYS$FORMAT_ACL(ACLENT(POINT:POINT-1+
+     &		ICHAR(ACLENT(POINT:POINT))),ACLLEN,ACLSTR,,,,)
+	   ELSE
+	      CALL INIT_ITMLST	! Initialize item list
+	      CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_FNDACETYP,%LOC(ACLENT))
+	      CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	      IER = SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST)
+     &				,,,CTXT,,)
+	      IER = SYS$FORMAT_ACL(ACLENT(:ICHAR(ACLENT(:1))),
+     &				ACLLEN,ACLSTR,,,,)
+	      CALL LIB$MOVC3(4,%REF(ACLENT(5:)),ACCESS)
+	      IF (ACCESS.EQ.0) IER = .FALSE.
+	   END IF
+	   AC = INDEX(ACLSTR,',ACCESS')
+	   IF ((ACC_TYPE.EQ.1.AND.INDEX(ACLSTR(AC:),'WRITE').GT.0).OR.
+     &	       (ACC_TYPE.EQ.2.AND.INDEX(ACLSTR(AC:),'READ').GT.0.AND.
+     &	        INDEX(ACLSTR(AC:),'WRITE').EQ.0)) THEN
+	      START_ID = INDEX(ACLSTR,'=') + 1
+	      END_ID = INDEX(ACLSTR,',ACCESS') - 1
+	      IF (ACLSTR(END_ID:END_ID).EQ.']') THEN
+		 START_ID = END_ID - 1
+		 ASCII = .FALSE.
+		 DO WHILE (ACLSTR(START_ID:START_ID).NE.'['.AND.
+     &			   ACLSTR(START_ID:START_ID).NE.'='.AND.
+     &			   (ACLSTR(START_ID:START_ID).NE.','.OR..NOT.ASCII))
+		    IF (ACLSTR(START_ID:START_ID).NE.','.AND.
+     &			(ACLSTR(START_ID:START_ID).LT.'0'.OR.
+     &			 ACLSTR(START_ID:START_ID).GT.'9')) ASCII = .TRUE.
+		    IF (ACLSTR(START_ID:START_ID).NE.','.OR..NOT.ASCII) THEN
+		       START_ID = START_ID - 1
+	 	    END IF
+		 END DO
+		 IF (ASCII) THEN
+		    START_ID = START_ID + 1
+		    END_ID = END_ID - 1
+		    IF (ACLSTR(START_ID:START_ID).EQ.'*') THEN
+		       START_ID = INDEX(ACLSTR,'=') + 1
+	               END_ID = INDEX(ACLSTR,'ACCESS') - 2
+		    END IF
+		 END IF
+	      END IF
+	      IF (OUTLEN.EQ.0) THEN
+		IF (FILENAME.NE.BULLUSER_FILE) THEN
+	         IF (ACC_TYPE.EQ.1) THEN
+		    WRITE (6,'(
+     &		    '' These users can read and write to this folder:'')')
+	         ELSE
+		    WRITE (6,'(
+     &		    '' These users can only read this folder:'')')
+	         END IF
+		ELSE
+		 WRITE (6,'('' The following are rights identifiers'',
+     &			'' which will give privileges.'')')
+		END IF
+		OUTLEN = 1
+	      END IF
+	      IDLEN = END_ID - START_ID + 1
+	      IF (OUTLEN+IDLEN-1.GT.80) THEN
+		 WRITE (6,'(1X,A)') OUTPUT(:OUTLEN-1)
+		 OUTPUT = ACLSTR(START_ID:END_ID)//','
+		 OUTLEN = IDLEN + 2
+	      ELSE IF (OUTLEN+IDLEN-1.EQ.80) THEN
+		 WRITE (6,'(1X,A)') 
+     &			OUTPUT(:OUTLEN-1)//ACLSTR(START_ID:END_ID)
+	         OUTLEN = 1
+	      ELSE
+	         OUTPUT(OUTLEN:) = ACLSTR(START_ID:END_ID)//','
+		 OUTLEN = OUTLEN + IDLEN + 1
+	      END IF
+	   END IF
+	   POINT = POINT + ICHAR(ACLENT(POINT:POINT))
+	 END DO
+	 IF (OUTLEN.GT.1) WRITE (6,'(1X,A)') OUTPUT(:OUTLEN-2)
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CONVERT_INFFILE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	OPEN (UNIT=10,FILE=BULLINF_FILE,STATUS='OLD',
+     &	   ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	   IOSTAT=IER,ORGANIZATION='INDEXED',
+     &	   KEY=(1:12:CHARACTER))
+
+	INQUIRE (UNIT=10,RECORDSIZE=RECL)
+
+	IF ((RECL-3)/2.GT.FOLDER_MAX) THEN
+	   WRITE (6,'('' ERROR: Old data files have more folders'',
+     &		      '' than was specified with BULLUSER.INC.'')')
+	   WRITE (6,'('' Recompile with correct FOLDER_MAX.'')')
+	   IF (USERNAME.EQ.'DECNET') THEN
+	      CALL SYS$DELPRC(,)
+	   ELSE
+	      CALL ENABLE_CTRL
+	      CALL SYS$CANEXH()
+	      CALL EXIT
+	   END IF
+	END IF
+
+	RECL = (RECL-3)/2
+
+	OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='NEW',
+     &	   ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=FOLDER_MAX*2+3,
+     &	   IOSTAT=IER,ORGANIZATION='INDEXED',
+     &	   KEY=(1:12:CHARACTER))
+
+	DO WHILE (IER.EQ.0)
+	 READ (10,IOSTAT=IER) TEMP_USER,((LAST_READ_BTIM(J,I),J=1,2),I=1,RECL)
+	 IF (IER.EQ.0) WRITE (9) TEMP_USER,
+     &			((LAST_READ_BTIM(J,I),J=1,2),I=1,FOLDER_MAX)
+	END DO
+
+	CLOSE (UNIT=10,STATUS='DELETE')
+
+	CLOSE (UNIT=9)
+
+	RETURN
+	END
+
+
+	SUBROUTINE ERROR_AND_EXIT
+
+	IMPLICIT INTEGER (A-Z)
+	
+	CALL ERRSNS(IDUMMY,IER)
+	CALL SYS_GETMSG(IER)
+	CALL ENABLE_CTRL_EXIT
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE COPY_ACL(INFILE,OUTFILE)
+C
+C  SUBROUTINE COPY_ACL
+C
+C  FUNCTION:
+C	Copy ACLs from one file to another file
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER*(*) INFILE,OUTFILE
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,ACL$C_ACLLENGTH,%LOC(ACLLENGTH))
+				! Get length needed to store acl output
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST),,,,,)
+
+	CALL LIB$GET_VM(ACLLENGTH+12,ACLSTR)	! Create character string to
+	CALL MAKE_CHAR(%VAL(ACLSTR),ACLLENGTH,ACLLENGTH)	! store acl
+
+	CALL COPY_ACL1(INFILE,OUTFILE,%VAL(ACLSTR),ACLLENGTH)
+						! Pass location of string
+	CALL LIB$FREE_VM(ACLLENGTH+12,ACLSTR)
+
+	RETURN
+	END
+
+
+	SUBROUTINE COPY_ACL1(INFILE,OUTFILE,ACLENT,ACLLENGTH)
+C
+C  SUBROUTINE COPY_ACL1
+C
+C  FUNCTION: Called by COPY_ACL to actually do the copy.  Need 2 routines
+C	since must convert location of string into a character string.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER ACLENT*(*),INFILE*(*),OUTFILE*(*)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_READACL,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST),,,,,)
+				! Read input file acl
+
+	IF (.NOT.IER) THEN
+	   IER = SYS$PARSE_ACL('(ID=*,ACCESS=NONE)',ACLENT,,)
+	   IF (.NOT.IER) RETURN
+	   ACLLENGTH = ACL$S_ADDACLENT
+	   CTXT = 0
+	   DO WHILE (IER)
+	      CALL INIT_ITMLST	! Initialize item list
+	      CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_ADDACLENT,
+     &				%LOC(ACLENT))
+	      CALL END_ITMLST(ACL1_ITMLST)	! Get address of itemlist
+	      IER = SYS$CHANGE_ACL
+     &			(,ACL$C_FILE,OUTFILE,%VAL(ACL1_ITMLST),,,)
+
+	      CALL INIT_ITMLST	! Initialize item list
+	      CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_FNDACETYP,%LOC(ACLENT))
+	      CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	      IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST)
+     &				,,,CTXT,,)
+	      CALL LIB$MOVC3(4,%REF(ACLENT(5:)),ACCESS)
+	      IF (ACCESS.EQ.0) RETURN		! ID=*, ACCESS=NONE, which has
+						! (and must) be applied first
+	   END DO
+	   RETURN
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+
+	POINT = 1
+	DO WHILE (POINT.LT.ACLLENGTH)	! Transfer all acls to output file
+	   CALL ADD_2_ITMLST(ICHAR(ACLENT(POINT:POINT)),ACL$C_ADDACLENT,
+     &		%LOC(ACLENT(POINT:)))
+	   POINT = POINT + ICHAR(ACLENT(POINT:POINT))
+	END DO
+
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,OUTFILE,%VAL(ACL_ITMLST),,,)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CHECK_DIR_ACCESS()
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*80 TEST,TEST1
+
+	DATA CHECKED /.FALSE./
+
+  	IF (CHECKED) RETURN
+
+	CHECKED = .TRUE.
+
+	IF (SYS_TRNLNM_SYSTEM(FOLDER_DIRECTORY,TEST)) THEN 
+	   IER = SYS_TRNLNM(FOLDER_DIRECTORY,TEST1)
+	   IF (IER) IER = TEST.NE.TEST1
+	   IF (IER) THEN 
+	      TEST1 = BULLNEWS_FILE
+	      CALL ADD_DIRECTORY(BULLNEWS_FILE)
+	      C = 0
+	      IER = LIB$FIND_FILE(BULLNEWS_FILE,BULLNEWS_FILE,C)
+	      BULLNEWS_FILE = TEST1
+	   END IF
+	   IF (.NOT.IER) THEN  
+	      TEST1 = FOLDER_DIRECTORY
+	      FOLDER_DIRECTORY = TEST
+	   END IF
+	   CALL ADD_DIRECTORY(BULLNEWS_FILE)
+	   IF (.NOT.IER) FOLDER_DIRECTORY = TEST1
+	ELSE
+	   CALL ADD_DIRECTORY(BULLNEWS_FILE)
+	END IF
+
+	CALL CHECK_DIR(FOLDER_DIRECTORY,.FALSE.)
+	CALL CHECK_DIR(NEWS_DIRECTORY,.FALSE.)
+
+	CALL ADD_DIRECTORIES
+
+        RETURN
+        END
+ 
+
+
+	SUBROUTINE ADD_DIRECTORIES
+
+        INCLUDE 'BULLFILES.INC'
+
+	CALL ADD_DIRECTORY(BULLUSER_FILE)
+	CALL ADD_DIRECTORY(BULLFOLDER_FILE)
+	CALL ADD_DIRECTORY(BULLINF_FILE)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION CHECK_DIR(DIRECTORY,LIBRARY)
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*(*) DIRECTORY
+
+	CHARACTER*80 TEST,TEST1
+
+	CHECK_DIR = PRESENT(BULLUSER_FILE,DIRECTORY,TEST).AND.
+     &		    PRESENT(BULLFOLDER_FILE,DIRECTORY,TEST).AND.
+     &		    PRESENT(BULLINF_FILE,DIRECTORY,TEST)
+
+	IF (CHECK_DIR) THEN
+	   IF (SYS_TRNLNM(DIRECTORY,TEST)) DIRECTORY = TEST
+	   RETURN
+	END IF
+
+	TEST = ' '
+
+	IF (INDEX(DIRECTORY,']').EQ.0) THEN
+	   CALL SYS_TRNLNM(DIRECTORY,TEST1)
+	ELSE
+	   TEST1 = DIRECTORY
+	END IF
+
+	IER = 1
+	DO WHILE (TEST.NE.TEST1.AND.IER)
+	   IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',TEST)
+	END DO
+
+	IF (.NOT.LIBRARY.AND.TEST.EQ.' ') THEN
+	   IER = SYS_TRNLNM_SYSTEM(DIRECTORY,TEST)
+	   IF (.NOT.IER.AND.TEST1.EQ.DIRECTORY) RETURN
+	END IF
+
+	IF (TEST.NE.TEST1) THEN
+	   IF (LIBRARY) THEN
+	      WRITE (6,'('' ERROR: Not a valid library. '')')
+	      RETURN
+	   END IF
+           IF (INDEX(TEST1,':').EQ.0) TEST1 = TEST1(:TRIM(TEST1))//':'
+	   CALL DISABLE_PRIVS
+	   OPEN(UNIT=3,FILE=TEST1(:TRIM(TEST1))//
+     &		'BULL.SCR',STATUS='NEW',IOSTAT=IER)
+	   CLOSE(UNIT=3,STATUS='DELETE')
+	   CALL ENABLE_PRIVS
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR: No access to directory: '',A)')
+     &		TEST1(:TRIM(TEST1))
+	      CALL EXIT
+	   END IF
+	   DIRECTORY = TEST1
+	ELSE
+           IF (INDEX(TEST,':').EQ.0) TEST = TEST(:TRIM(TEST))//':'
+	   DIRECTORY = TEST
+    	   DO WHILE (IER)
+	      IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',TEST)
+	   END DO
+	   CHECK_DIR = .TRUE.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION PRESENT(FILE,DIR,TEST)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) FILE,DIR,TEST
+
+	FILE = FILE(INDEX(FILE,':')+1:)
+	FILE = FILE(INDEX(FILE,']')+1:)
+        IF (INDEX(DIR,':').EQ.0.AND.INDEX(DIR,'[').EQ.0.AND.
+     &	    INDEX(DIR,'<').EQ.0) DIR = DIR(:TRIM(DIR))//':'
+	C = 0
+	PRESENT = LIB$FIND_FILE(DIR(:TRIM(DIR))//FILE,TEST,C)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE ADD_DIRECTORY(DIRECTORY)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*(*) DIRECTORY
+
+	DIRECTORY = DIRECTORY(INDEX(DIRECTORY,':')+1:)
+	DIRECTORY = DIRECTORY(INDEX(DIRECTORY,']')+1:)
+        IF (INDEX(FOLDER_DIRECTORY,':').EQ.0) FOLDER_DIRECTORY 
+     &			= FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//':'
+	DIRECTORY = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &			//DIRECTORY
+
+	RETURN
+        END
+
+
+
+	SUBROUTINE SET_LIBRARY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+ 
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+        CALL CLI$GET_VALUE('LIBRARY',BULL_PARAMETER,LEN_P)
+
+	IF (CHECK_DIR(BULL_PARAMETER,.TRUE.)) THEN
+	   FOLDER_DIRECTORY = BULL_PARAMETER
+	   CALL ADD_DIRECTORIES
+	   FOLDER_SET = .FALSE.
+           FOLDER_NUMBER = 0
+           CALL SELECT_FOLDER(.FALSE.,IER)
+           WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &              FOLDER(:TRIM(FOLDER))
+	   CALL UPDATE_USERINFO
+	   CALL OPEN_USERINFO
+	   INCMD = 'SHOW'
+	   CALL UPDATE_READ(0)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SHOW_LIBRARY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	IF (CLI$PRESENT('ALL')) THEN 
+	   IER = 1
+	   N = 1
+	   DO WHILE (IER)
+	      IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',BULL_PARAMETER)
+	      IF (IER) THEN
+	         IF (N.EQ.1) THEN
+	            WRITE (6,'('' The following are valid libraries:'')')
+	   	    N = 0
+	         END IF
+	         WRITE (6,'(1X,A)') BULL_PARAMETER
+	      END IF
+	   END DO
+	   IF (N.EQ.1) WRITE (6,'('' No libraries are present.'')')
+	ELSE
+	   WRITE (6,'('' Present library is: '',A)')
+     &		FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_BULLNEWSDIR_FILE(FN)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+  
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+
+	BULLNEWSDIR_FILE = ' '
+  
+	ENCODE(6,'(I6)',BULLNEWSDIR_FILE) FN
+	BULLNEWSDIR_FILE = BULLNEWSDIR_FILE(FIRST_ALPHA(BULLNEWSDIR_FILE):)
+	L = TRIM(BULLNEWSDIR_FILE)
+
+	BULLNEWSDIR_FILE = FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWSDIR.'//
+     &		BULLNEWSDIR_FILE(:L-3)//']'//
+     &		BULLNEWSDIR_FILE(L-2:TRIM(BULLNEWSDIR_FILE))//'.'
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin7.for b/decus/vmslt00a/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..d845a8531050d5773f709b8fd766b48cf88aaf15
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin7.for
@@ -0,0 +1,2374 @@
+C
+C  BULLETIN7.FOR, Version 11/3/98
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE UPDATE_LOGIN(ADD_BULL)
+C
+C  SUBROUTINE UPDATE_LOGIN
+C
+C  FUNCTION:  Updates the login file when a bulletin has been deleted
+C	or added.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	DIMENSION READ_BTIM_SAVE(2),TEMP_BTIM(2)
+
+	IF (FOLDER_NUMBER.GE.1000) GO TO 1000
+
+C
+C  We want to keep the last read date for comparison when selecting new
+C  folders, so save it for later restoring.
+C
+
+	READ_BTIM_SAVE(1) = READ_BTIM(1)
+	READ_BTIM_SAVE(2) = READ_BTIM(2)
+
+	CALL OPEN_BULLUSER_SHARED
+
+C
+C  Newest date/time in user file only applies to general bulletins.
+C  This was present before adding folder capability.
+C  We set flags in user entry to show new folder added for folder bulletins.
+C  However, the newest bulletin for each folder is not continually updated,
+C  As it is only used when comparing to the last bulletin read time, and to
+C  store this for each folder would be too expensive.
+C
+
+	TEMP_BTIM(1) = NEWEST_BTIM(1)
+	TEMP_BTIM(2) = NEWEST_BTIM(2)
+	CALL READ_USER_FILE_HEADER(IER)
+	NEWEST_BTIM(1) = TEMP_BTIM(1)
+	NEWEST_BTIM(2) = TEMP_BTIM(2)
+
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLUSER
+	   RETURN
+	ELSE IF (FOLDER_NUMBER.EQ.0) THEN
+	   CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,NEWEST_BTIM)
+	   REWRITE (4,IOSTAT=IER) USER_HEADER
+	END IF
+
+1000	BROAD_MSG = .FALSE.
+	IF (ADD_BULL.AND.FOLDER_NUMBER.GE.0) THEN	! Message added?
+	   IF (INCMD(:3).NE.'ADD') THEN
+	      BROAD_MSG = .TRUE.
+	   ELSE IF (.NOT.CLI$PRESENT('BROADCAST')) THEN
+	      BROAD_MSG = .TRUE.
+	   END IF
+	END IF
+
+	IF (BROAD_MSG) THEN
+	   IF (BTEST(FOLDER_FLAG,0)) THEN		! Folder protected?
+	      CALL CHKACL
+     &		(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',IER)
+	      IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	         CHECK_ACL = 0
+	      ELSE
+	         CHECK_ACL = 1
+	      END IF
+	   ELSE
+	       CHECK_ACL = 0
+	   END IF
+
+ 	   CALL NOTIFY_USERS(CHECK_ACL)
+	END IF
+
+	IF (FOLDER_NUMBER.GE.1000) RETURN
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+		! Reobtain present values as calling programs still uses them
+
+	READ_BTIM(1) = READ_BTIM_SAVE(1)
+	READ_BTIM(2) = READ_BTIM_SAVE(2)
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE NOTIFY_USERS(CHECK_ACL)
+C
+C  SUBROUTINE NOTIFY_USERS
+C
+C  FUNCTION: Notify users with SET NOTIFY set of new message.
+C
+	IMPLICIT INTEGER (A - Z)
+	
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($BRKDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER OUTPUT*160,TERMINAL*8,FLAGS*4
+	CHARACTER*12 SENT_TEMP_USER,TEMP_USERNAME
+	CHARACTER NEWS_ACCESS*132
+	CHARACTER FOLDER_NAME_SAVE*80
+
+	INTEGER SAVE_LAST_NEWS_READ(2,FOLDER_MAX)
+
+	PARAMETER CR=CHAR(13),LF=CHAR(10),BELL=CHAR(7)
+
+	DATA FIRST/.TRUE./, BROAD1_USER_QUEUE/0/, TEMP_USER_QUEUE/0/
+
+	OUTPUT = BELL//CR//LF//LF//
+     &		'New bulletin added to folder '//FOLDER_NAME(:
+     &		TRIM(FOLDER_NAME))
+     &		//'. From: '//FROM(:TRIM(FROM))//CR//LF//
+     &		'Description: '//DESCRIP(:TRIM(DESCRIP))
+
+	IF (FIRST) THEN
+	   IER = SYS_TRNLNM('BULL_SYSTEM_FLAGS',FLAGS)
+	   IF (.NOT.IER) THEN
+	      IER = SYS_TRNLNM('MAIL$SYSTEM_FLAGS',FLAGS)
+	   END IF
+
+	   BFLAG = 0
+	   READ (FLAGS(:1),'(I1)',IOSTAT=IER) FLAG
+	   IF (BTEST(FLAG,1).AND.IER.EQ.0) BFLAG = BRK$M_CLUSTER
+	   FIRST = .FALSE.
+	   FOLDER1_NAME = ' '
+	END IF
+
+	CALL SYS$SETRWM(%VAL(1))		! Don't wait if can't broadcast
+
+	CALL INIT_QUEUE(BROAD1_USER_QUEUE,TEMP_USERNAME)
+	BROAD_USER_QUEUE = BROAD1_USER_QUEUE
+	IF (FOLDER_NAME_SAVE.EQ.FOLDER_NAME) THEN 
+           TEMP_USERNAME = ' '
+	   DO WHILE (TEMP_USERNAME.NE.'*')
+	      CALL READ_QUEUE(%VAL(BROAD_USER_QUEUE),BROAD_USER_QUEUE,
+     &				   TEMP_USERNAME)
+	      IF (TEMP_USERNAME.NE.'*') THEN
+	         CALL SYS$BRKTHRU(,OUTPUT(:TRIM(OUTPUT))//CR,
+     &			TEMP_USERNAME(:TRIM(TEMP_USERNAME)),
+     &			%VAL(BRK$C_USERNAME),,,%VAL(BFLAG),,%VAL(5),,)
+	      END IF
+	   END DO
+           CALL SYS$SETRWM(%VAL(0))
+	   RETURN
+	END IF
+
+	FOLDER_NAME_SAVE = FOLDER_NAME
+
+	IF (REMOTE_SET.EQ.4) THEN
+	   CALL OPEN_BULLINF_SHARED
+           CALL LIB$MOVC3(4*2*FOLDER_MAX,LAST_NEWS_READ,
+     &				SAVE_LAST_NEWS_READ)
+	END IF
+
+	CALL INIT_QUEUE(TEMP_USER_QUEUE,TEMP_USERNAME)
+	CALL INIT_QUEUE(BROAD1_USER_QUEUE,TEMP_USERNAME)
+	WRITE_TEMP_QUEUE = TEMP_USER_QUEUE
+	BROAD_USER_QUEUE = BROAD1_USER_QUEUE
+
+	DO WHILE (GETUSERS(TEMP_USERNAME,TERMINAL))
+	   READ_TEMP_QUEUE = TEMP_USER_QUEUE
+	   SENT_TEMP_USER = ' '
+	   DO WHILE (TEMP_USERNAME.NE.SENT_TEMP_USER.AND.
+     &				READ_TEMP_QUEUE.NE.WRITE_TEMP_QUEUE)
+		 CALL READ_QUEUE(%VAL(READ_TEMP_QUEUE),READ_TEMP_QUEUE,
+     &				SENT_TEMP_USER)
+	   END DO
+	   IF (TEMP_USERNAME.NE.SENT_TEMP_USER) THEN
+              IF (REMOTE_SET.EQ.4) THEN 
+	         CALL READ_NEWS_USERINFO(TEMP_USERNAME,IER)
+	      ELSE
+	         CALL READ_USER_FILE_KEYNAME(TEMP_USERNAME,IER)
+	      END IF
+              CALL WRITE_QUEUE(%VAL(WRITE_TEMP_QUEUE),WRITE_TEMP_QUEUE,
+     &				TEMP_USERNAME)
+	   ELSE
+	      IER = 2
+	   END IF
+	   IF (IER.EQ.0.AND.TEMP_USERNAME.NE.FROM.AND.
+     &	       TEST_NOTIFY_FLAG(FOLDER_NUMBER)) THEN
+	      IF (CHECK_ACL) THEN
+	         IF (REMOTE_SET.EQ.4) THEN
+	            CALL CHECK_ACCESS
+     &		     (NEWS_ACCESS(FOLDER_DESCRIP),
+     &		     TEMP_USERNAME,IER,WRITE_ACCESS)
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',
+     &		     TEMP_USERNAME,IER,WRITE_ACCESS)
+	         END IF
+	      ELSE
+		 IER = 1
+	      END IF
+	      IF (IER) THEN
+		 CALL SYS$BRKTHRU(,OUTPUT(:TRIM(OUTPUT))//CR,
+     &			TEMP_USERNAME(:TRIM(TEMP_USERNAME)),
+     &			%VAL(BRK$C_USERNAME),,,%VAL(BFLAG),,%VAL(5),,)
+                 CALL WRITE_QUEUE(%VAL(BROAD_USER_QUEUE),
+     &					BROAD_USER_QUEUE,TEMP_USERNAME)
+	      ELSE IF (REMOTE_SET.LT.3) THEN 
+		 CALL CLR2(NOTIFY_FLAG,FOLDER_NUMBER)
+	         REWRITE (4,IOSTAT=IER) TEMP_USERNAME//USER_ENTRY(13:)
+	      END IF
+	   END IF
+	END DO
+	CALL SYS$SETRWM(%VAL(0))
+
+        IF (REMOTE_SET.EQ.4) THEN
+           CALL CLOSE_BULLINF
+           CALL LIB$MOVC3(4*2*FOLDER_MAX,SAVE_LAST_NEWS_READ,
+     &				LAST_NEWS_READ)
+        END IF
+
+	FOLDER1_NAME = FOLDER_NAME
+
+	TEMP_USERNAME = '*'
+        CALL WRITE_QUEUE(%VAL(BROAD_USER_QUEUE),BROAD_USER_QUEUE,
+     &				TEMP_USERNAME)
+
+	RETURN
+	END
+
+
+
+
+ 
+	SUBROUTINE ADD_ENTRY
+C
+C  SUBROUTINE ADD_ENTRY
+C
+C  FUNCTION: Enters a new directory entry in the directory file.
+C
+	IMPLICIT INTEGER (A - Z)
+	
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	
+	CHARACTER TODAY_TIME*32
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+        COMMON /LOCALPOST/ LOCAL_POST
+
+	IF (REMOTE_SET) THEN
+	   LOCAL = .TRUE.
+	   IF (INCMD(:3).EQ.'ADD') LOCAL = CLI$PRESENT('LOCAL')
+	   IF (LOCAL) THEN
+	      WRITE (REMOTE_UNIT,'(9A)',IOSTAT=IER)
+     &			3,DESCRIP,EXDATE,EXTIME,SYSTEM,0,0,0,0
+	   ELSE
+	      WRITE (REMOTE_UNIT,'(9A)',IOSTAT=IER)
+     &		3,DESCRIP,EXDATE,EXTIME,SYSTEM,CLI$PRESENT('BROADCAST'),
+     &		CLI$PRESENT('BELL'),CLI$PRESENT('ALL'),
+     &		CLI$PRESENT('CLUSTER')
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (I.EQ.LEN(FOLDER1_COM)) THEN
+	         IER = SYS$ASCTIM(,TODAY_TIME,F1_NEWEST_BTIM,)
+	         NEWEST_DATE = TODAY_TIME(:11)
+	         NEWEST_TIME = TODAY_TIME(13:23)
+	         NBULL = F1_NBULL
+		 CALL UPDATE_FOLDER
+	      ELSE
+		 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      END IF
+	   ELSE
+	      CALL DISCONNECT_REMOTE
+	      IF (INCMD(:4).EQ.'MOVE') CALL EXIT
+	   END IF
+	   CALL UPDATE_LOGIN(.TRUE.)
+	   RETURN
+	END IF
+
+	CALL READDIR(0,IER)
+
+	IF (IER.NE.1) THEN
+	   NEWEST_EXDATE = '5-NOV-2056'
+	   NEWEST_EXTIME = '00:00:00.00'
+	   NEWEST_DATE = '5-NOV-1956'
+	   NEWEST_TIME = '00:00:00.00'
+	   NBULL = 0
+	   IF (REMOTE_SET.NE.4) NBLOCK = 0
+	   SHUTDOWN = 0
+	   NEMPTY = 0
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY_TIME,,)
+       	NEWEST_DATE = TODAY_TIME(:11)  
+	NEWEST_TIME = TODAY_TIME(13:23)
+	IF (.NOT.LOCAL_POST) THEN
+	   DATE = NEWEST_DATE
+	   TIME = NEWEST_TIME
+	END IF
+	 
+	IF (.NOT.BTEST(FOLDER_FLAG,13)) THEN
+	   DIFF = COMPARE_DATE(NEWEST_EXDATE,EXDATE)
+	   IF (DIFF.GT.0) THEN
+	      NEWEST_EXDATE = EXDATE
+	      NEWEST_EXTIME = EXTIME
+	   ELSE IF (DIFF.EQ.0) THEN
+	      DIFF = COMPARE_TIME(NEWEST_EXTIME,EXTIME)
+	      IF (DIFF.GT.0) NEWEST_EXTIME = EXTIME
+	   END IF
+	END IF
+
+	IF ((SYSTEM.AND.4).EQ.4) THEN
+	   SHUTDOWN = SHUTDOWN + 1
+	   SHUTDOWN_DATE = DATE
+	   SHUTDOWN_TIME = TIME
+	END IF
+
+	IF (REMOTE_SET.EQ.4) THEN
+	   BLOCK = NBLOCK - LENGTH
+	   CALL WRITEDIR(NEWS_F_END+1,IER)
+	ELSE
+	   BLOCK = NBLOCK + 1
+	   CALL WRITEDIR(NBULL+1,IER)
+	END IF
+
+	IF (IER.NE.0) RETURN
+
+	IF (REMOTE_SET.EQ.4) THEN
+	   NEWS_F_END = NEWS_F_END + 1
+           NBULL = NEWS_F_END
+	   F_NBULL = NEWS_F_END
+	ELSE
+	   NBULL = NBULL + 1
+ 	   NBLOCK = NBLOCK + LENGTH
+	END IF
+
+	CALL WRITEDIR(0,IER)
+
+	IF (BTEST(FOLDER_FLAG,13)) THEN
+    	   CALL READ_FIRST_EXPIRED(NDEL)
+	   DO WHILE (NDEL.GT.0.AND.NDEL.LE.NEWS_F_END.AND.
+     &		COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).LT.0)
+	      IF (LENGTH.GT.0) CALL DUMP_MESSAGE()
+	      DELETE (UNIT=2)
+    	      CALL READ_FIRST_EXPIRED(NDEL)
+	   END DO
+	   CALL OPEN_BULLNEWS_SHARED
+	   CALL READ_FOLDER_FILE_KEYNAME(NEWS_FOLDER,IER)
+	   FOLDER_FLAG = IBCLR(FOLDER_FLAG,13)
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLNEWS
+	END IF
+
+	INQUIRE (UNIT=2,OPENED=IER)
+	IF (IER) CALL CLOSE_BULLDIR
+	CALL UPDATE_LOGIN(.TRUE.)
+	IF (IER) CALL OPEN_BULLDIR
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION COMPARE_BTIM(BTIM1,BTIM2)
+C
+C  FUNCTION COMPARE_BTIM
+C
+C  FUCTION: Compares times in binary format to see which is farther in future.
+C
+C  INPUTS:
+C	BTIM1  -  First time in binary format
+C	BTIM2  -  Second time in binary format
+C  OUTPUT:
+C	Returns +1 if first time is farther in future
+C	Returns -1 if second time is farther in future
+C	Returns 0 if equal time
+C
+	IMPLICIT INTEGER (A - Z)
+
+	DIMENSION BTIM1(2),BTIM2(2),DIFF(2)
+
+	CALL LIB$SUBX(BTIM1,BTIM2,DIFF)
+
+	IF (DIFF(2).LT.0) THEN
+	   COMPARE_BTIM = -1
+	ELSE IF (DIFF(2).GE.0) THEN
+	   COMPARE_BTIM = +1
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	INTEGER FUNCTION MINUTE_DIFF(DATE2,DATE1)
+C
+C  FUNCTION MINUTE_DIFF
+C
+C  FUNCTION: Finds difference in minutes between 2 binary times.
+C
+C
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION DATE1(2),DATE2(2)
+
+	CALL LIB$DAY(DAYS1,DATE1,MSECS1)
+	CALL LIB$DAY(DAYS2,DATE2,MSECS2)
+
+	MINUTE_DIFF = (DAYS2-DAYS1)*24*60 + (MSECS2-MSECS1)/6000
+
+	RETURN
+	END
+
+
+
+
+
+ 
+	INTEGER FUNCTION COMPARE_DATE(DATE1,DATE2)
+C
+C  FUNCTION COMPARE_DATE
+C
+C  FUCTION: Compares dates to see which is farther in future.
+C
+C  INPUTS:
+C	DATE1  -  First date  (dd-mm-yy)
+C	DATE2  -  Second date (If is equal to ' ', then use present date)
+C  OUTPUT:
+C	Returns the difference in days between the two dates.
+C	If the DATE1 is farther in the future, the output is positive,
+C	else it is negative.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	CHARACTER*(*) DATE1,DATE2
+	INTEGER USER_TIME(2)
+
+	CALL SYS_BINTIM(DATE1,USER_TIME)
+
+	CALL VERIFY_DATE(USER_TIME)
+C
+C  LIB$DAY crashes if date invalid, which happened once due to an unknown
+C  hardware or software error which created a date very far in the future.
+C
+	CALL LIB$DAY(DAY1,USER_TIME)
+
+	IF (DATE2.NE.' ') THEN
+	   CALL SYS_BINTIM(DATE2,USER_TIME)
+	   CALL VERIFY_DATE(USER_TIME)
+	ELSE
+	   CALL SYS$GETTIM(USER_TIME)
+	END IF
+
+	CALL LIB$DAY(DAY2,USER_TIME)
+
+	COMPARE_DATE = DAY1 - DAY2
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE VERIFY_DATE(BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION BTIM(2),TEMP(2)
+
+	CALL SYS_BINTIM(' 5-NOV-2011 00:00:00.00',TEMP)
+
+	IER = COMPARE_BTIM(BTIM,TEMP)
+
+	IF (IER.GT.0) THEN		! Date invalid
+	   BTIM(1) = TEMP(1)
+	   BTIM(2) = TEMP(2)
+	END IF
+
+	CALL SYS_BINTIM(' 5-NOV-1955 00:00:00.00',TEMP)
+
+	IER = COMPARE_BTIM(BTIM,TEMP)
+
+	IF (IER.LT.0) THEN		! Date invalid
+	   BTIM(1) = TEMP(1)
+	   BTIM(2) = TEMP(2)
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION COMPARE_TIME(TIME1,TIME2)
+C
+C  FUNCTION COMPARE_TIME
+C
+C  FUCTION: Compares times to see which is farther in future.
+C
+C  INPUTS:
+C	TIME1  -  First time	(hh:mm:ss.xx)
+C	TIME2  -  Second time
+C  OUTPUT:
+C	Outputs (TIME1-TIME2) in seconds.  Thus, if TIME1 is further
+C	in the future, outputs positive number, else negative.
+C
+
+	IMPLICIT INTEGER (A-Z)
+	CHARACTER*(*) TIME1,TIME2
+	CHARACTER*24 TODAY_TIME
+	CHARACTER*12 TEMP2
+
+	IF (TIME2.EQ.' ') THEN
+	   CALL SYS$ASCTIM(,TODAY_TIME,,)
+	   TEMP2 = TODAY_TIME(13:23)
+	ELSE
+	   TEMP2 = TIME2
+	END IF
+
+	COMPARE_TIME = 3600*10*(ICHAR(TIME1(:1))-ICHAR(TEMP2(:1)))
+     &		         +3600*(ICHAR(TIME1(2:2))-ICHAR(TEMP2(2:2)))
+     &		        +60*10*(ICHAR(TIME1(4:4))-ICHAR(TEMP2(4:4)))
+     &		           +60*(ICHAR(TIME1(5:5))-ICHAR(TEMP2(5:5)))
+     &		           +10*(ICHAR(TIME1(7:7))-ICHAR(TEMP2(7:7)))
+     &		              +(ICHAR(TIME1(8:8))-ICHAR(TEMP2(8:8)))
+
+	IF (COMPARE_TIME.EQ.0) THEN
+	   COMPARE_TIME = 10*(ICHAR(TIME1(10:10))-ICHAR(TEMP2(10:10)))
+     &		            +(ICHAR(TIME1(11:11))-ICHAR(TEMP2(11:11)))
+	   IF (COMPARE_TIME.GT.0) THEN
+	      COMPARE_TIME = 1
+	   ELSE IF (COMPARE_TIME.LT.0) THEN
+	      COMPARE_TIME = -1
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+C-------------------------------------------------------------------------
+C
+C  The following are subroutines to create a linked-list queue for 
+C  temporary buffer storage of data that is read from files to be
+C  outputted to the terminal.  This is done so as to be able to close
+C  the file as soon as possible.
+C
+C  Each record in the queue has the following format.  The first two
+C  words are used for creating a character variable.  The first word
+C  contains the length of the character variable, the second contains
+C  the address.  The address is simply the address of the 3rd word of
+C  the record.  The last word in the record contains the address of the
+C  next record.  Every time a record is written, if that record has a
+C  zero link, it adds a new record for the next write operation. 
+C  Therefore, there will always be an extra record in the queue.  To
+C  check for the end of the queue, the last word (link to next record)
+C  is checked to see if it is zero. 
+C
+C-------------------------------------------------------------------------
+	SUBROUTINE INIT_QUEUE(HEADER,DATA)
+	CHARACTER*(*) DATA
+	INTEGER HEADER
+	IF (HEADER.NE.0) RETURN		! Queue already initialized
+	LENGTH = LEN(DATA)
+	IF (MOD(LENGTH,4).NE.0) LENGTH = LENGTH + 4 - MOD(LENGTH,4)
+	CALL LIB$GET_VM(LENGTH+12,HEADER)
+	CALL MAKE_CHAR(%VAL(HEADER),LEN(DATA),LENGTH)
+	RETURN
+	END
+
+
+	SUBROUTINE WRITE_QUEUE(RECORD,NEXT,DATA)
+	INTEGER RECORD(1)
+	CHARACTER*(*) DATA
+	LENGTH = RECORD(1)
+	CALL COPY_CHAR(LENGTH,DATA,%VAL(%LOC(RECORD)))
+	IF (MOD(LENGTH,4).NE.0) LENGTH = LENGTH + 4 - MOD(LENGTH,4)
+	NEXT = RECORD((LENGTH+12)/4)
+	IF (NEXT.NE.0) RETURN
+	CALL LIB$GET_VM(LENGTH+12,NEXT)
+	CALL MAKE_CHAR(%VAL(NEXT),RECORD(1),LENGTH)
+	RECORD((LENGTH+12)/4) = NEXT
+	RETURN
+	END
+
+	SUBROUTINE READ_QUEUE(RECORD,NEXT,DATA)
+	CHARACTER*(*) DATA
+	INTEGER RECORD(1)
+	LENGTH = RECORD(1)
+	CALL COPY_CHAR(LENGTH,%VAL(%LOC(RECORD)),DATA)
+	IF (MOD(LENGTH,4).NE.0) LENGTH = LENGTH + 4 - MOD(LENGTH,4)
+	NEXT = RECORD((LENGTH+12)/4)
+	RETURN
+	END
+
+	SUBROUTINE COPY_CHAR(LENGTH,INCHAR,OUTCHAR)
+	CHARACTER*(*) INCHAR,OUTCHAR
+	OUTCHAR = INCHAR(:LENGTH)
+	RETURN
+	END
+
+	SUBROUTINE MAKE_CHAR(IARRAY,CHAR_LEN,REAL_LEN)
+	IMPLICIT INTEGER (A-Z)
+	DIMENSION IARRAY(1)
+	IARRAY(1) = CHAR_LEN
+	IARRAY(2) = %LOC(IARRAY(3))
+	IARRAY(REAL_LEN/4+3) = 0
+	RETURN
+	END
+
+
+
+	SUBROUTINE DISABLE_PRIVS
+C
+C  SUBROUTINE DISABLE_PRIVS
+C
+C  FUNCTION: Disable image high privileges.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	COMMON /PRIVS/ SETPRV,PRV_DEPTH
+	DIMENSION SETPRV(2)
+
+	DATA PRV_DEPTH /0/
+
+	COMMON /REALPROC/ REALPROCPRIV(2)
+
+	PRV_DEPTH = PRV_DEPTH + 1
+
+	IF (PRV_DEPTH.GT.1) RETURN
+
+	CALL SYS$SETPRV(%VAL(0),,,SETPRV)	! Get privileges
+
+	SETPRV(1) = SETPRV(1).AND..NOT.REALPROCPRIV(1)
+
+	CALL SYS$SETPRV(%VAL(0),SETPRV,,)	! Disable installed privs
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ENABLE_PRIVS
+C
+C  SUBROUTINE ENABLE_PRIVS
+C
+C  FUNCTION: Enable image high privileges.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVS/ SETPRV,PRV_DEPTH
+	DIMENSION SETPRV(2)
+
+	PRV_DEPTH = PRV_DEPTH - 1
+
+	IF (PRV_DEPTH.GT.1) RETURN
+
+	CALL SYS$SETPRV(%VAL(1),SETPRV,,)	! Enable image privs
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CHECK_PRIV_IO(ERROR)
+C
+C  SUBROUTINE CHECK_PRIV_IO
+C
+C  FUNCTION: Checks SYS$OUTPUT and SYS$ERROR to see if they need
+C	privileges to output to.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /OUTPUT/ REASSIGNED
+	LOGICAL REASSIGNED
+	DATA REASSIGNED /.FALSE./
+
+	CALL DISABLE_PRIVS			! Disable SYSPRV 
+
+	IF (.NOT.REASSIGNED) THEN
+	   OPEN (UNIT=6,FILE='SYS$OUTPUT',IOSTAT=IER,STATUS='NEW')
+	   CLOSE (UNIT=6,STATUS='DELETE')
+	END IF
+
+	OPEN (UNIT=4,FILE='SYS$ERROR',IOSTAT=IER1,STATUS='NEW')
+	IF (IER.NE.0.OR.IER1.NE.0) THEN
+	   IF (IER1.EQ.0) WRITE (4,100)
+	   IF (IER.EQ.0) WRITE (6,200)
+	   ERROR = 1
+	ELSE
+	   CLOSE (UNIT=4,STATUS='DELETE')
+	   ERROR = 0
+	END IF
+
+	CALL ENABLE_PRIVS			! Enable SYSPRV 
+
+100	FORMAT(1X,'ERROR: SYS$OUTPUT cannot be opened.')
+200	FORMAT(1X,'ERROR: SYS$ERROR cannot be opened.')
+
+	RETURN
+	END
+
+
+	SUBROUTINE CHANGE_FLAG(CMD,FLAG)
+C
+C  SUBROUTINE CHANGE_FLAG
+C
+C  FUNCTION: Sets flags for specified folder.
+C
+C  INPUTS:
+C	CMD    -   LOGICAL*4 value. If TRUE, set flag. 
+C		   If FALSE, clear flag.
+C	FLAG	-  If 1, modify NEW_FLAG, if 2, modify SET_FLAG
+C		   If 3, modify BRIEF_FLAG, 4, modify NOTIFY_FLAG
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	DIMENSION FLAGS(FLONG,4)
+	EQUIVALENCE (NEW_FLAG(1),FLAGS(1,1))
+
+	LOGICAL CMD
+
+	DIMENSION READ_BTIM_SAVE(2)
+
+	DATA CHANGE_FOLDER /.FALSE./
+
+	IF (CLI$PRESENT('FOLDER')) THEN
+	   IER = CLI$GET_VALUE('FOLDER',FOLDER1)
+	   IF (IER) THEN
+	      FOLDER_NUMBER_SAVE = FOLDER_NUMBER
+	      CALL OPEN_BULLFOLDER_SHARED
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	      CALL CLOSE_BULLFOLDER
+	      IF (IER.NE.0) THEN
+	         WRITE (6,'('' ERROR: No such folder found.'')')
+	         RETURN
+	      ELSE IF (INDEX(FOLDER1,'.').GT.0.OR.
+     &		 (FOLDER1(:1).GE.'a'.AND.FOLDER1(:1).LE.'z')) THEN
+	         WRITE (6,'('' ERROR: Command not valid for folder.'')')
+	         RETURN
+	      END IF
+	   END IF
+	   FOLDER_NUMBER = FOLDER1_NUMBER
+	   CHANGE_FOLDER = .TRUE.
+	END IF
+
+C
+C  Find user entry in BULLUSER.DAT to update information.
+C
+
+	ENTRY CHANGE_FLAG_NOCMD(CMD,FLAG)
+
+	CALL OPEN_BULLUSER_SHARED		! Open user file
+
+	READ_BTIM_SAVE(1) = READ_BTIM(1)
+	READ_BTIM_SAVE(2) = READ_BTIM(2)
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)	! Read old entry
+
+	IF (IER.GT.0) THEN 		! No entry (how did this happen??)
+	   CALL SYS_BINTIM('-',LOGIN_BTIM)	! Get today's today
+	   CALL SYS_BINTIM('5-NOV-1956 11:05:56',READ_BTIM)	! Fake new entry
+	   CALL READ_USER_FILE_HEADER(IER)
+	   IF (CMD) THEN
+	      CALL SET2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   ELSE
+	      CALL CLR2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   END IF
+	   NEW_FLAG(1) = 143
+	   NEW_FLAG(2) = 0
+	   CALL WRITE_USER_FILE_NEW(IER)
+	ELSE
+	   IF (CMD) THEN
+	      CALL SET2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   ELSE
+	      CALL CLR2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   END IF
+	   NEW_FLAG(1) = 143
+	   REWRITE (4,IOSTAT=IER) USER_ENTRY
+	   READ_BTIM(1) = READ_BTIM_SAVE(1)
+	   READ_BTIM(2) = READ_BTIM_SAVE(2)
+	END IF
+
+	IF (CMD.AND.FLAG.EQ.4.AND.FOLDER_BBOARD(:2).EQ.'::') THEN
+	   DO WHILE (REC_LOCK(IER))
+	      READ (4,KEY='*NOTIFY',IOSTAT=IER) TEMP_USER,NOTIFY_REMOTE
+	   END DO
+
+	   IF (IER.NE.0) THEN
+	      DO I=1,FLONG
+	         NOTIFY_REMOTE(I) = 0
+	      END DO
+	      CALL SET2(NOTIFY_REMOTE,FOLDER_NUMBER)
+	      WRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	   ELSE
+	      CALL SET2(NOTIFY_REMOTE,FOLDER_NUMBER)
+	      REWRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	IF (CHANGE_FOLDER) THEN
+	   FOLDER_NUMBER = FOLDER_NUMBER_SAVE
+	   CHANGE_FOLDER = .FALSE.
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE SET_VERSION
+C
+C  SUBROUTINE SET_VERSION
+C
+C  FUNCTION: Sets version number.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	DIMENSION FLAGS(FLONG,4)
+	EQUIVALENCE (NEW_FLAG(1),FLAGS(1,1))
+
+	DIMENSION READ_BTIM_SAVE(2)
+
+C
+C  Find user entry in BULLUSER.DAT to update information.
+C
+
+	CALL OPEN_BULLUSER_SHARED		! Open user file
+
+	READ_BTIM_SAVE(1) = READ_BTIM(1)
+	READ_BTIM_SAVE(2) = READ_BTIM(2)
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)	! Read old entry
+
+	IF (IER.EQ.0) THEN
+	   NEW_FLAG(1) = 143
+	   REWRITE (4,IOSTAT=IER) USER_ENTRY  ! Write modified entry
+	   READ_BTIM(1) = READ_BTIM_SAVE(1)
+	   READ_BTIM(2) = READ_BTIM_SAVE(2)
+	END IF
+
+	CALL CLOSE_FILE (4)
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE CHECK_NEWUSER(USERNAME,DISMAIL,PASSCHANGE)
+C
+C  SUBROUTINE CHECK_NEWUSER
+C
+C  FUNCTION: Checks flags for a new: Whether DISMAIL is set,
+C		and what the last password change was.
+C
+C  INPUTS:
+C	USERNAME  -  Username
+C  OUTPUTS:
+C  	DISMAIL     -  Returns 1 if account has DISMAIL.
+C		       returns 0 if account has no DISMAIL.
+C	PASSCHANGE  -  Date of last password change.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) USERNAME
+
+	INTEGER PASSCHANGE(2)
+
+	INCLUDE '($UAIDEF)'
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(4,UAI$_FLAGS,%LOC(FLAGS))
+	CALL ADD_2_ITMLST(8,UAI$_PWD_DATE,%LOC(PASSCHANGE))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	DISMAIL = 0					! Set return false
+	IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)	! Read Record
+	IF (IER) THEN					! If username found
+	   IF (BTEST(FLAGS,UAI$V_NOMAIL)) THEN		! DISMAIL SET?
+	      DISMAIL = 1				! Yep
+	   END IF
+	END IF
+
+	RETURN						! Return
+	END						! End
+
+
+
+	INTEGER FUNCTION SYS_TRNLNM(INPUT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+        PARAMETER LNM$_STRING = '2'X
+
+	IF (INDEX(INPUT,']').GT.0) THEN
+	   SYS_TRNLNM = .FALSE.
+	   RETURN
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+	IF (OUTPUT.NE.'DEFINED') CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT),%LOC(OLEN))
+	CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+
+	EINPUT = INDEX(INPUT,':') - 1
+	IF (EINPUT.LE.0) EINPUT = TRIM(INPUT)
+
+	SYS_TRNLNM = SYS$TRNLNM(,'LNM$FILE_DEV',INPUT(:EINPUT),,
+     &		%VAL(TRNLNM_ITMLST))
+
+	IF (SYS_TRNLNM.AND.OUTPUT.NE.'DEFINED') OUTPUT = OUTPUT(:OLEN)
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION SYS_TRNLNM_SYSTEM_INDEX(INPUT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+        PARAMETER LNM$_STRING = '2'X
+	PARAMETER LNM$_INDEX = '1'X
+	PARAMETER LNM$_MAX_INDEX = '7'X
+
+	DATA NINDEX /0/
+
+	IF (MAX_INDEX.LT.NINDEX) THEN
+	   NINDEX = 0
+	   SYS_TRNLNM_SYSTEM_INDEX = 0
+	   RETURN
+	END IF
+
+	EINPUT = INDEX(INPUT,':') - 1
+	IF (EINPUT.LE.0) EINPUT = TRIM(INPUT)
+
+	IF (NINDEX.EQ.0) THEN 
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(4,LNM$_MAX_INDEX,%LOC(MAX_INDEX))
+	   CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+ 	   SYS_TRNLNM_SYSTEM_INDEX = SYS$TRNLNM(,'LNM$SYSTEM',
+     &		INPUT(:EINPUT),,%VAL(TRNLNM_ITMLST))
+	   IF (.NOT.SYS_TRNLNM_SYSTEM_INDEX) RETURN
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,LNM$_INDEX,%LOC(NINDEX))
+	CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT),%LOC(OLEN))
+	CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+
+	SYS_TRNLNM_SYSTEM_INDEX = SYS$TRNLNM(,'LNM$SYSTEM',
+     &		INPUT(:EINPUT),,%VAL(TRNLNM_ITMLST))
+
+	IF (SYS_TRNLNM_SYSTEM_INDEX) OUTPUT = OUTPUT(:OLEN)
+	NINDEX = NINDEX  + 1
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION SYS_TRNLNM_SYSTEM(INPUT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+        PARAMETER LNM$_STRING = '2'X
+
+	CALL INIT_ITMLST	! Initialize item list
+	IF (OUTPUT.NE.'DEFINED') CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT),%LOC(OLEN))
+	CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+
+	EINPUT = INDEX(INPUT,':') - 1
+	IF (EINPUT.LE.0) EINPUT = TRIM(INPUT)
+
+	SYS_TRNLNM_SYSTEM = SYS$TRNLNM(,'LNM$SYSTEM',
+     &		INPUT(:EINPUT),,%VAL(TRNLNM_ITMLST))
+
+	IF (SYS_TRNLNM_SYSTEM.AND.OUTPUT.NE.'DEFINED') THEN
+	   OUTPUT = OUTPUT(:OLEN)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION FILE_LOCK(IER,IER1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($RMSDEF)'
+
+	DATA INIT /.TRUE./
+
+	IF (INIT) THEN
+	   FILE_LOCK = 1
+	   INIT = .FALSE.
+	   IER1 = 0
+	ELSE
+	   IF (IER.GT.0) THEN
+	      IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	      IF (IER1.EQ.RMS$_FLK) THEN
+	         FILE_LOCK = 1
+		 CALL WAIT_SEC('01')
+	      ELSE
+	         FILE_LOCK = 0
+	         INIT = .TRUE.
+	      END IF
+	   ELSE
+	      FILE_LOCK = 0
+	      IER1 = 0
+	      INIT = .TRUE.
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ENABLE_CTRL
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /CTRL_LEVEL/ LEVEL
+
+	COMMON /DEF_PROT/ ORIGINAL_DEF_PROT
+
+        COMMON /KEYPAD/ KEYPAD_MODE
+
+	QUIT = 1
+
+	ENTRY ENABLE_CTRL_EXIT
+
+	QUIT = QUIT.AND.1		! If called via entry, QUIT = 0
+	IF (QUIT.EQ.1) LEVEL = LEVEL - 1
+
+	IF (LEVEL.LT.0.AND.QUIT.EQ.1) THEN
+	   WRITE (6,'('' ERROR: Error in CTRL.'')')
+	END IF
+
+	IF (LEVEL.EQ.0.OR.QUIT.EQ.0) THEN
+	   CALL LIB$ENABLE_CTRL(CTRLY,)	! Enable CTRL-Y & -C
+	END IF
+
+	IF (QUIT.EQ.0) THEN
+	   IF (KEYPAD_MODE.EQ.0) THEN
+	      IER = SMG$CREATE_VIRTUAL_KEYBOARD(KEYBOARD_ID,,,,)
+	      IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,1)
+	   END IF
+	   CALL CLOSE_TAG
+	   FOLDER_FLAG = 0
+	   CALL SET_FOLDER_FILE(0)
+	   CALL UPDATE_USERINFO
+	   CALL PRINT_NOW
+	   CALL SYS$SETDFPROT(ORIGINAL_DEF_PROT,)
+	   CALL EXIT
+	END IF
+	QUIT = 0			! Reinitialize
+
+	RETURN
+	END
+
+
+	SUBROUTINE DISABLE_CTRL
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /CTRL_LEVEL/ LEVEL
+	DATA LEVEL /0/
+
+	IF (LEVEL.EQ.0) CALL LIB$DISABLE_CTRL(CTRLY,)
+	LEVEL = LEVEL + 1
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CLEANUP_BULLFILE
+C
+C  SUBROUTINE CLEANUP_BULLFILE
+C
+C  FUNCTION:  Searches for empty space in bulletin file and deletes it.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	CHARACTER BUFFER*128
+
+	CALL OPEN_BULLDIR
+
+C
+C  NOTE: Can't use READDIR for reading header since it'll spawn a 
+C  BULL/CLEANUP.  (Fooey).
+C
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (2,KEYID=0,KEY=HEADER_KEY,IOSTAT=IER) BULLDIR_HEADER
+	END DO
+
+	IF (NEMPTY.EQ.0) THEN		! No cleanup necessary
+	 CALL CLOSE_BULLDIR
+	 RETURN
+	ELSE IF (NEMPTY.GT.0) THEN
+
+	 IER = 1
+	 DO WHILE (IER)
+	    IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.TMPDIR;-1')
+	 END DO
+
+	 IER = 1
+	 DO WHILE (IER)
+	    IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.TMPFIL;-1')
+	 END DO
+
+	 CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,,)
+
+	 OPEN (UNIT=11,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL',
+     1	      STATUS='UNKNOWN',IOSTAT=IER,DISPOSE='DELETE',
+     1	      RECORDTYPE='FIXED',RECORDSIZE=32,
+     1	      FORM='UNFORMATTED',INITIALSIZE=((NBLOCK-NEMPTY)*128)/512)
+				! Compressed version is number 1
+
+	 IF (IER.NE.0) THEN
+	    WRITE (6,'('' Cannot open temporary file for''
+     &		,'' compressing '',A)') FOLDER(:TRIM(FOLDER))
+	    CALL ERRSNS(IDUMMY,IER)
+	    IF (IER1.EQ.0) THEN
+	       WRITE (6,'('' IOSTAT error = '',I)') IER
+	    ELSE
+	       CALL SYS_GETMSG(IER1)
+	    END IF
+	    CALL CLOSE_BULLDIR
+	    CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+	    RETURN
+	 END IF
+
+	 CALL COPY_ACL(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',
+     &		       FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL')
+
+	 CALL OPEN_BULLFIL_SHARED
+
+	 NBLOCK = 0
+
+	 DO I=1,NBULL				! Copy bulletins to new file
+	   CALL READDIR(I,IER)
+	   ICOUNT = BLOCK
+	   DO J=1,LENGTH
+	      NBLOCK = NBLOCK + 1
+	      DO WHILE (REC_LOCK(IER1))
+	         READ(1'ICOUNT,IOSTAT=IER1) BUFFER
+	      END DO
+	      IF (IER1.NE.0) THEN		! This file is corrupt
+		 NBLOCK = NBLOCK - 1
+		 NBULL = I - 1
+	         GO TO 100
+	      END IF
+	      WRITE(11) BUFFER
+	      ICOUNT = ICOUNT + 1
+	   END DO
+	 END DO
+
+100	 CALL CLOSE_BULLFIL
+	ELSE IF (NEMPTY.EQ.-1) THEN
+	 IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL',
+     &				'*.BULLFIL')
+	 IER = 1
+	 DO WHILE (IER)
+	    IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLFIL;-1')
+	 END DO
+	 IER = 1
+	 DO WHILE (IER)
+	    IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLDIR;-1')
+	 END DO
+	 IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &			'.BULL*','*.*;1')
+	 NEMPTY = 0
+	 REWRITE (2,IOSTAT=IER) BULLDIR_HEADER
+	 CALL CLOSE_BULLDIR
+	 RETURN
+	END IF
+
+	OPEN (UNIT=12,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.TMPDIR',STATUS='UNKNOWN',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED',
+     &	      INITIALSIZE=(((NBULL+1)*DIR_RECORD_LENGTH)/512)+1 )
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=12,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.TMPDIR',STATUS='UNKNOWN',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	    IF (IER.NE.0) THEN
+	       WRITE (6,'('' Cannot open temporary file for''
+     &		,'' compressing '',A)') FOLDER(:TRIM(FOLDER))
+	       CALL ERRSNS(IDUMMY,IER)
+	       IF (IER1.EQ.0) THEN
+	          WRITE (6,'('' IOSTAT error = '',I)') IER
+	       ELSE
+	          CALL SYS_GETMSG(IER1)
+	       END IF
+	       CLOSE (UNIT=11)
+	       CALL CLOSE_BULLDIR
+	       CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+	       RETURN
+	    END IF
+	END IF
+
+	CALL COPY_ACL(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLDIR',
+     &		       FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPDIR')
+
+	NEMPTY = -1
+	WRITE (12,IOSTAT=IER) BULLDIR_HEADER	! Write directory header
+
+	NBLOCK = 0		! Update directory entry pointers
+	DO I=1,NBULL
+	   CALL READDIR(I,IER)
+	   BLOCK = NBLOCK + 1
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   WRITE (12,IOSTAT=IER) BULLDIR_ENTRY
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' Cannot write to temporary file for''
+     &		,'' compressing '',A)') FOLDER(:TRIM(FOLDER))
+	      CALL ERRSNS(IDUMMY,IER)
+	      IF (IER1.EQ.0) THEN
+	         WRITE (6,'('' IOSTAT error = '',I)') IER
+	      ELSE
+	         CALL SYS_GETMSG(IER1)
+	      END IF
+	      CLOSE (UNIT=12)
+	      CLOSE (UNIT=11)
+	      CALL CLOSE_BULLDIR
+	      CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+	      RETURN
+	   END IF
+	   NBLOCK = NBLOCK + MAX(LENGTH,0)
+	END DO
+
+	CLOSE (UNIT=12,STATUS='KEEP')
+	CLOSE (UNIT=11,STATUS='KEEP')
+
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPDIR',
+     &				'*.BULLDIR')
+	CALL CLOSE_BULLDIR_DELETE
+
+	IER = 1
+	DO WHILE (IER)
+	   IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLDIR;-1')
+	END DO
+
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL',
+     &				'*.BULLFIL')
+	IER = 1
+	DO WHILE (IER)
+	   IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLFIL;-1')
+	END DO
+
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &			'.BULL*','*.*;1')
+
+	CALL OPEN_BULLDIR
+	DO WHILE (REC_LOCK(IER))
+	   READ (2,KEYID=0,KEY=HEADER_KEY,IOSTAT=IER) BULLDIR_HEADER
+	END DO
+
+	IF (NEMPTY.EQ.-1) THEN
+	   NEMPTY = 0
+	   REWRITE (2,IOSTAT=IER) BULLDIR_HEADER
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CLEANUP_DIRFILE(DELETE_ENTRY)
+C
+C  SUBROUTINE CLEANUP_DIRFILE
+C
+C  FUNCTION:  Reorder directory file after deletions.
+C	      Is called either directly after a deletion, or is
+C	      called if it is detected that a deletion was not fully
+C	      completed due to the fact that the deleting process
+C	      was abnormally terminated.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(DIR_RECORD_LENGTH) BULLDIR_ENTRY_SAVE
+
+	CHARACTER*12 DATE_SAVE,EXDATE_SAVE
+	CHARACTER*12 TIME_SAVE,EXTIME_SAVE
+
+	BULLDIR_ENTRY_SAVE = BULLDIR_ENTRY
+	DATE_SAVE = DATE
+	TIME_SAVE = TIME
+	EXDATE_SAVE = EXDATE
+	EXTIME_SAVE = EXTIME
+
+	NBULL = -NBULL		! Negative # Bulls signals deletion in progress
+	MOVE_TO = 0		! Moving directory entries starting here
+	MOVE_FROM = 0		! Moving directory entries from here
+	I = DELETE_ENTRY	! Start search point for first deleted entries
+	DO WHILE (MOVE_TO.EQ.0.AND.I.LE.NBULL)
+	   CALL READDIR(I,IER)
+	   IF (IER.NE.I+1) THEN	! Have we found a deleted entry?
+	      MOVE_TO = I	! If so, start moving entries to here
+	      J=I+1		! Search for next entry in file
+	      DO WHILE (MOVE_FROM.EQ.0.AND.J.LE.NBULL)
+		 CALL READDIR(J,IER)
+		 IF (IER.EQ.J+1) MOVE_FROM = J
+		 J = J + 1
+	      END DO
+	      IF (MOVE_FROM.EQ.0) THEN	! There are no more entries
+		 NBULL = I - 1		! so just update number of bulletins
+		 CALL WRITEDIR(0,IER)
+		 RETURN
+	      END IF
+	      LENGTH = -LENGTH		! Indicate starting point by writing
+	      CALL WRITEDIR(I,IER)	! next entry into deleted entry
+	      FIRST_DELETE = I		! with negative length
+	      MOVE_FROM = MOVE_FROM + 1	! Set up pointers to move rest of
+	      MOVE_TO = MOVE_TO + 1	! the entries
+	   ELSE IF (LENGTH.LT.0) THEN	! If negative length found, deletion
+	      FIRST_DELETE = I		! was previously in progress
+	      J = I			! Try to find where entry came from
+	      CALL INIT_QUEUE(ENTRY_Q1,BULLDIR_ENTRY)
+	      ENTRY_Q = ENTRY_Q1
+	      DO K=J,NBULL
+		 CALL READDIR(K,IER)
+	         IF (IER.EQ.K+1) THEN
+		    CALL WRITE_QUEUE(%VAL(ENTRY_Q),ENTRY_Q,BULLDIR_ENTRY)
+		 END IF
+	      END DO
+	      ENTRY_QLAST = ENTRY_Q
+	      ENTRY_Q2 = ENTRY_Q1
+	      DO WHILE (MOVE_FROM.EQ.0.AND.ENTRY_Q2.NE.ENTRY_QLAST)
+		 CALL READ_QUEUE(%VAL(ENTRY_Q2),ENTRY_Q,BULLDIR_ENTRY)
+		 ENTRY_Q2 = ENTRY_Q
+		 BLOCK_SAVE = BLOCK
+		 MSG_NUM_SAVE = MSG_NUM
+		 DO WHILE (MOVE_FROM.EQ.0.AND.ENTRY_Q.NE.ENTRY_QLAST)
+						! Search for duplicate entries
+		    CALL READ_QUEUE(%VAL(ENTRY_Q),ENTRY_Q,BULLDIR_ENTRY)
+		    IF (BLOCK_SAVE.EQ.BLOCK) THEN
+		       MOVE_TO = MSG_NUM_SAVE + 1
+		       MOVE_FROM = MSG_NUM + 1
+		    END IF
+		 END DO
+		 			! If no duplicate entry found for this
+					! entry, see if one exists for any
+	      END DO			! of the other entries
+	   END IF
+	   I = I + 1
+	END DO
+
+	IF (I.LE.NBULL) THEN		! Move reset of entries if necessary
+	   IF (MOVE_FROM.GT.0) THEN
+	      DO J=MOVE_FROM,NBULL
+	         CALL READDIR(J,IER)
+		 IF (IER.EQ.J+1) THEN	! Skip any other deleted entries
+		    CALL WRITEDIR(MOVE_TO,IER)
+		    MOVE_TO = MOVE_TO + 1
+		 END IF
+	      END DO
+	   END IF
+	   DO J=MOVE_TO,NBULL		! Delete empty records at end of file
+	      CALL READDIR(J,IER)
+	      DELETE(UNIT=2,IOSTAT=IER)
+	   END DO
+	   NBULL = MOVE_TO - 1		! Update # bulletin count
+	END IF
+
+	IF (FIRST_DELETE.GT.0) THEN
+	   CALL READDIR(FIRST_DELETE,IER)
+	   IF (IER.EQ.FIRST_DELETE+1.AND.LENGTH.LT.0) THEN
+	      LENGTH = -LENGTH		! Fix entry which has negative length
+	      CALL WRITEDIR(FIRST_DELETE,IER)
+	   END IF
+	END IF
+
+	CALL WRITEDIR(0,IER)
+
+	BULLDIR_ENTRY = BULLDIR_ENTRY_SAVE
+	DATE = DATE_SAVE
+	TIME = TIME_SAVE
+	EXDATE = EXDATE_SAVE
+	EXTIME = EXTIME_SAVE
+
+	RETURN
+	END
+
+
+	SUBROUTINE SHOW_FLAGS
+C
+C  SUBROUTINE SHOW_FLAGS
+C
+C  FUNCTION: Show user flags.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (FOLDER_NUMBER.LT.0) THEN
+	   WRITE (6,'('' ERROR: Cannot show flags for remote folder.'')')
+	   RETURN
+	END IF
+
+C
+C  Find user entry in BULLUSER.DAT to obtain flags.
+C
+	IF (REMOTE_SET.LT.3) THEN
+	   CALL OPEN_BULLUSER_SHARED		! Open user file
+	   CALL READ_USER_FILE_KEYNAME(USERNAME,IER)	! Read old entry
+	ELSE IF (NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: NEWS FOLDER is not subscribed.'')')
+           RETURN
+ 	END IF
+
+	WRITE (6,'('' For the selected folder '',A)')
+     &	   FOLDER_NAME(:TRIM(FOLDER_NAME))
+
+	IF (TEST_SET_FLAG(FOLDER_NUMBER).AND.
+     &	   (.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER))) THEN
+	   WRITE (6,'('' READNEW is set.'')')
+	ELSE IF (TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &	       TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' BRIEF is set.'')')
+	ELSE IF (TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &	       .NOT.TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' SHOWNEW is set.'')')
+	END IF
+
+	IF (REMOTE_SET.NE.3.AND.TEST_NOTIFY_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' NOTIFY is set.'')')
+	ELSE IF (.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &	       .NOT.TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' No flags are set.'')')
+	END IF
+
+	IF (REMOTE_SET.LT.3) CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET2(FLAG,NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER FLAG(2)
+
+	F_POINT = NUMBER/32 + 1
+	FLAG(F_POINT) = IBSET(FLAG(F_POINT),NUMBER-32*(F_POINT-1))
+
+	RETURN
+	END
+
+
+	SUBROUTINE CLR2(FLAG,NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER FLAG(3)
+
+	F_POINT = NUMBER/32 + 1
+	FLAG(F_POINT) = IBCLR(FLAG(F_POINT),NUMBER-32*(F_POINT-1))
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST2(FLAG,NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER FLAG(3)
+
+	F_POINT = NUMBER/32 + 1
+	TEST2 = BTEST(FLAG(F_POINT),NUMBER-32*(F_POINT-1))
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION GETUSERS(USERNAME,TERMINAL)
+C
+C  FUNCTION GETUSERS
+C
+C  FUNCTION:
+C	To get names of all users that are logged in.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+!*** MODULE $PSCANDEF ***
+	PARAMETER PSCAN$_BEGIN = '00000000'X
+	PARAMETER PSCAN$_ACCOUNT = '00000001'X
+	PARAMETER PSCAN$_AUTHPRI = '00000002'X
+	PARAMETER PSCAN$_CURPRIV = '00000003'X
+	PARAMETER PSCAN$_GRP = '00000004'X
+	PARAMETER PSCAN$_HW_MODEL = '00000005'X
+	PARAMETER PSCAN$_HW_NAME = '00000006'X
+	PARAMETER PSCAN$_JOBPRCCNT = '00000007'X
+	PARAMETER PSCAN$_JOBTYPE = '00000008'X
+	PARAMETER PSCAN$_MASTER_PID = '00000009'X
+	PARAMETER PSCAN$_MEM = '0000000A'X
+	PARAMETER PSCAN$_MODE = '0000000B'X
+	PARAMETER PSCAN$_NODE_CSID = '0000000C'X
+	PARAMETER PSCAN$_NODENAME = '0000000D'X	
+	PARAMETER PSCAN$_OWNER = '0000000E'X
+	PARAMETER PSCAN$_PRCCNT = '0000000F'X
+	PARAMETER PSCAN$_PRCNAM = '00000010'X
+	PARAMETER PSCAN$_PRI = '00000011'X
+	PARAMETER PSCAN$_PRIB = '00000012'X
+	PARAMETER PSCAN$_STATE = '00000013'X
+	PARAMETER PSCAN$_STS = '00000014'X
+	PARAMETER PSCAN$_TERMINAL = '00000015'X
+	PARAMETER PSCAN$_UIC = '00000016'X
+	PARAMETER PSCAN$_USERNAME = '00000017'X
+	PARAMETER PSCAN$_GETJPI_BUFFER_SIZE = '00000018'X
+	PARAMETER PSCAN$_END = '00000019'X
+	PARAMETER PSCAN$k_type = '00000081'X
+	PARAMETER PSCAN$M_OR = '00000001'X
+	PARAMETER PSCAN$M_BIT_ALL = '00000002'X
+	PARAMETER PSCAN$M_BIT_ANY = '00000004'X
+	PARAMETER PSCAN$M_GEQ = '00000008'X
+	PARAMETER PSCAN$M_GTR = '00000010'X
+	PARAMETER PSCAN$M_LEQ = '00000020'X
+	PARAMETER PSCAN$M_LSS = '00000040'X
+	PARAMETER PSCAN$M_PREFIX_MATCH = '00000080'X
+	PARAMETER PSCAN$M_WILDCARD = '00000100'X
+	PARAMETER PSCAN$M_CASE_BLIND = '00000200'X
+	PARAMETER PSCAN$M_EQL = '00000400'X
+	PARAMETER PSCAN$M_NEQ = '00000800'X
+	STRUCTURE /item_specific_flags/
+	    PARAMETER PSCAN$S_OR = 1
+	    PARAMETER PSCAN$V_OR = 0
+	    PARAMETER PSCAN$S_BIT_ALL = 1
+	    PARAMETER PSCAN$V_BIT_ALL = 1
+	    PARAMETER PSCAN$S_BIT_ANY = 1
+	    PARAMETER PSCAN$V_BIT_ANY = 2
+	    PARAMETER PSCAN$S_GEQ = 1
+	    PARAMETER PSCAN$V_GEQ = 3
+	    PARAMETER PSCAN$S_GTR = 1
+	    PARAMETER PSCAN$V_GTR = 4
+	    PARAMETER PSCAN$S_LEQ = 1
+	    PARAMETER PSCAN$V_LEQ = 5
+	    PARAMETER PSCAN$S_LSS = 1
+	    PARAMETER PSCAN$V_LSS = 6
+	    PARAMETER PSCAN$S_PREFIX_MATCH = 1
+	    PARAMETER PSCAN$V_PREFIX_MATCH = 7
+	    PARAMETER PSCAN$S_WILDCARD = 1
+	    PARAMETER PSCAN$V_WILDCARD = 8
+	    PARAMETER PSCAN$S_CASE_BLIND = 1
+	    PARAMETER PSCAN$V_CASE_BLIND = 9
+	    PARAMETER PSCAN$S_EQL = 1
+	    PARAMETER PSCAN$V_EQL = 10
+	    PARAMETER PSCAN$S_NEQ = 1
+	    PARAMETER PSCAN$V_NEQ = 11
+	BYTE %FILL (2)
+	END STRUCTURE
+
+	CHARACTER USERNAME*(*),TERMINAL*(*)
+C
+C	Replace all the lines in this subroutine with the following if
+C	you are running V5.2 or older.
+C
+C	DATA CONTEXT/-1/
+C	CALL INIT_ITMLST	! Initialize item list
+C				! Now add items to list
+C	CALL ADD_2_ITMLST(LEN(USERNAME),JPI$_USERNAME,%LOC(USERNAME))
+C	CALL ADD_2_ITMLST(LEN(TERMINAL),JPI$_TERMINAL,%LOC(TERMINAL))
+C	CALL ADD_2_ITMLST(4,JPI$_MODE,%LOC(UJPIMODE))
+C	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+C	IER = 1
+C	UJPIMODE = -1
+C	TERMINAL(1:1) = CHAR(0)
+C	DO WHILE (IER.AND.(TERMINAL(1:1).EQ.CHAR(0)).AND.(UJPIMODE.NE.
+C     *            JPI$K_INTERACTIVE))
+C						! Get next interactive process
+C	   IER = SYS$GETJPIW(,CONTEXT,,%VAL(GETJPI_ITMLST),,,,)
+C						! Get next process.
+C	END DO
+C	IF (.NOT.IER) CONTEXT = -1
+C  	GETUSERS = IER
+
+	DATA CONTEXT/0/
+
+	IF (CONTEXT.EQ.0) THEN 
+	   CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	   CALL ADD_2_ITMLST_WITH_RET(0,PSCAN$_NODE_CSID,0,PSCAN$M_NEQ)
+	   CALL ADD_2_ITMLST(0,PSCAN$_MODE,JPI$K_INTERACTIVE)
+	   CALL END_ITMLST(PSCAN_ITMLST)	! Get address of itemlist
+
+	   IER = SYS$PROCESS_SCAN(CONTEXT,%VAL(PSCAN_ITMLST))
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(LEN(USERNAME),JPI$_USERNAME,%LOC(USERNAME))
+	CALL ADD_2_ITMLST(LEN(TERMINAL),JPI$_TERMINAL,%LOC(TERMINAL))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = 1
+	TERMINAL(:1) = CHAR(0)
+	DO WHILE (IER.AND.TERMINAL(:1).EQ.CHAR(0))
+						! Get next interactive process
+	   IER = SYS$GETJPIW(,CONTEXT,,%VAL(GETJPI_ITMLST),,,,)
+						! Get next process.
+	END DO
+
+	IF (.NOT.IER) CONTEXT = 0
+
+	GETUSERS = IER
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE OPEN_USERINFO
+C
+C  SUBROUTINE OPEN_USERINFO
+C
+C  FUNCTION:  Opens the file in SYS$LOGIN which contains user information.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+	DATA USERINFO_READ /.FALSE./
+
+	INTEGER TODAY_BTIM(2)
+
+	CALL OPEN_BULLINF_SHARED
+
+	READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,LAST
+	DO I=1,FOLDER_MAX
+	   DO J=1,2
+	      LAST_READ_BTIM(J,I) = LAST(J,I)
+	   END DO
+	END DO
+
+	IF (IER.EQ.0) THEN		! Check to see if dates all in future
+	   CALL SYS_BINTIM('-',TODAY_BTIM)	! Get today's date
+	   CHANGED = .FALSE.
+	   DO I=1,FOLDER_MAX
+	      DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,I),TODAY_BTIM)
+	      IF (DIFF.GE.0) THEN	! Must have been in a time warp
+		 LAST_READ_BTIM(1,I) = TODAY_BTIM(1)
+		 LAST_READ_BTIM(2,I) = TODAY_BTIM(2)
+	         LAST(1,I) = TODAY_BTIM(1)
+	         LAST(2,I) = TODAY_BTIM(2)
+		 CHANGED = .TRUE.
+	      END IF
+	   END DO
+	   IF (CHANGED) REWRITE (9,IOSTAT=IER) USERNAME,LAST
+	END IF
+
+	IF (IER.NE.0.AND.TEST_BULLCP().EQ.2	! Is this BULLCP process?
+     &	    .AND.CONFIRM_USER(USERNAME).NE.0) THEN	! Not real user?
+	   USERNAME = 'DECNET'
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,LAST
+	   DO I=1,FOLDER_MAX
+	      DO J=1,2
+	         LAST_READ_BTIM(J,I) = LAST(J,I)
+	      END DO
+       	   END DO
+	END IF
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=10,FILE='SYS$LOGIN:BULLETIN.INF',STATUS='OLD',
+     &	      RECORDTYPE='FIXED',FORM='UNFORMATTED',IOSTAT=IER)
+	   INQUIRE(UNIT=10,RECORDSIZE=INF_SIZE)
+	   IF (IER.EQ.0) THEN
+	      READ (10)
+     &	  ((LAST_READ_BTIM(1,I),LAST_READ_BTIM(2,I)),I=1,INF_SIZE/2)
+	      CLOSE (UNIT=10,STATUS='DELETE')
+	   ELSE
+	      CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+	      CALL READ_USER_FILE_KEYNAME(USERNAME,IER)  ! Find user's info
+	      IF (IER.NE.0.AND.TEST_BULLCP().EQ.2) THEN	! BULLCP process?
+	         CALL SYS_BINTIM('-',LOGIN_BTIM)	! Get today's date
+	         CALL SYS_BINTIM('5-NOV-1956 11:05:56',READ_BTIM)
+		 CALL READ_USER_FILE_HEADER(IER)
+		 NEW_FLAG(1) = 143
+		 NEW_FLAG(2) = 0
+	         CALL WRITE_USER_FILE_NEW(IER)
+	      END IF
+	      CALL CLOSE_BULLUSER
+	      IF (IER.EQ.0) THEN
+	         DO I=1,FOLDER_MAX
+	            LAST_READ_BTIM(1,I) = READ_BTIM(1)
+	            LAST_READ_BTIM(2,I) = READ_BTIM(2)
+	         END DO
+	      END IF
+	   END IF
+  	   DO I=1,FOLDER_MAX
+	      DO J=1,2
+	         LAST(J,I) = LAST_READ_BTIM(J,I)
+	      END DO
+	   END DO
+	   IF (IER.EQ.0) WRITE (9,IOSTAT=IER) USERNAME,LAST
+           DO WHILE (REC_LOCK(IER))
+              READ (9,KEY='*DEFAULT',IOSTAT=IER) TEMP_USER,INF_REC
+	   END DO
+           IF (IER.EQ.0) THEN
+	      LU = TRIM(USERNAME)
+	      USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	      IF (LU.GT.1) THEN
+	         USERNAME(LU-1:LU-1) =
+     &			CHAR(128.OR.ICHAR(USERNAME(LU-1:LU-1)))
+	      ELSE
+	         USERNAME(2:2) = CHAR(128.OR.ICHAR(USERNAME(2:2)))
+	      END IF
+	      WRITE (9,IOSTAT=IER) USERNAME,INF_REC
+	      USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	      IF (LU.GT.1) THEN
+	         USERNAME(LU-1:LU-1) =
+     &			CHAR(127.AND.ICHAR(USERNAME(LU-1:LU-1)))
+	      ELSE
+	         USERNAME(2:2) = CHAR(127.AND.ICHAR(USERNAME(2:2)))
+	      END IF
+	   END IF
+	END IF
+
+	LU = TRIM(USERNAME)
+	USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	READ (9,KEY=USERNAME,IOSTAT=IER1) USERNAME,LAST_SYS_BTIM
+	USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	IF (IER1.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      LAST_SYS_BTIM(1,I) = 0
+	      LAST_SYS_BTIM(2,I) = 0
+	   END DO
+	END IF
+
+	CALL READ_NEWS_USERINFO(USERNAME,IER)
+
+	CALL CLOSE_BULLINF
+
+	CALL LIB$MOVC3(FOLDER_MAX*2*4,LAST_READ_BTIM(1,1)
+     &				,OLD_LAST_READ_BTIM)
+	CALL LIB$MOVC3(FOLDER_MAX*2*4,LAST_SYS_BTIM,OLD_LAST_SYS_BTIM)
+	CALL LIB$MOVC3(FOLDER_MAX*2*4,LAST_NEWS_READ,OLD_LAST_NEWS_READ)
+
+	USERINFO_READ = .TRUE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_NEWS_USERINFO(NAME,IER)
+C
+C  SUBROUTINE READ_NEWS_USERINFO
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER*(*) NAME
+	 
+	LU = TRIM(NAME)
+
+	NAME(LU:LU) = CHAR(128.OR.ICHAR(NAME(LU:LU)))
+	IF (LU.GT.1) THEN
+	   NAME(LU-1:LU-1) = CHAR(128.OR.ICHAR(NAME(LU-1:LU-1)))
+	ELSE
+	   NAME(2:2) = CHAR(128.OR.ICHAR(NAME(2:2)))
+	END IF
+	READ (9,KEY=NAME,IOSTAT=IER) NAME,LAST_NEWS_READ
+	NAME(LU:LU) = CHAR(127.AND.ICHAR(NAME(LU:LU)))
+	IF (LU.GT.1) THEN
+	   NAME(LU-1:LU-1) = CHAR(127.AND.ICHAR(NAME(LU-1:LU-1)))
+	ELSE
+	   NAME(2:2) = CHAR(127.AND.ICHAR(NAME(2:2)))
+	END IF
+	IF (IER.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      LAST_NEWS_READ(1,I) = 0
+	      LAST_NEWS_READ(2,I) = 0
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE UPDATE_USERINFO
+C
+C  SUBROUTINE UPDATE_USERINFO
+C
+C  FUNCTION:  Updates the latest message read times for each folder.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+	EQUIVALENCE (OLD_LAST_NEWS_READ2(1,1),OLD_LAST_NEWS_READ(1,1))
+	INTEGER*2 OLD_LAST_NEWS_READ2(4,FOLDER_MAX)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_FOLDER/ LAST_FOLDER_NUMBER 
+
+	IF (.NOT.USERINFO_READ) RETURN
+
+	DIFF = .FALSE.
+	IF (REMOTE_SET.EQ.0.OR.REMOTE_SET.EQ.1) THEN 
+	   DIFF = (LAST_READ_BTIM(1,LAST_FOLDER_NUMBER+1).NE.
+     &		  OLD_LAST_READ_BTIM(1,LAST_FOLDER_NUMBER+1)).OR.
+     &		  (LAST_READ_BTIM(2,LAST_FOLDER_NUMBER+1).NE.
+     &		  OLD_LAST_READ_BTIM(2,LAST_FOLDER_NUMBER+1))
+	END IF
+
+	DIFF1 = .FALSE.
+	IF (REMOTE_SET.EQ.0.OR.REMOTE_SET.EQ.1) THEN 
+	   DIFF1 = (LAST_SYS_BTIM(1,LAST_FOLDER_NUMBER+1).NE.
+     &	      	   OLD_LAST_SYS_BTIM(1,LAST_FOLDER_NUMBER+1)).OR.
+     &	       	   (LAST_SYS_BTIM(2,LAST_FOLDER_NUMBER+1).NE.
+     &		   OLD_LAST_SYS_BTIM(2,LAST_FOLDER_NUMBER+1))
+	END IF
+
+	DIFF2 = .FALSE.
+        GO TO 10
+	
+	ENTRY UPDATE_USERINFO_NEWS_ALWAYS
+	DIFF2 = .TRUE.
+
+10	IF (.NOT.DIFF2) THEN
+  	   DO I=1,FOLDER_MAX
+	      DIFF2 = (LAST_NEWS_READ(1,I).NE.
+     &	      	   OLD_LAST_NEWS_READ(1,I)).OR.
+     &	       	   (LAST_NEWS_READ(2,I).NE.
+     &		   OLD_LAST_NEWS_READ(2,I)).OR.DIFF2
+	   END DO
+	END IF
+
+	IF (.NOT.(DIFF.OR.DIFF1.OR.DIFF2)) RETURN
+
+	CALL OPEN_BULLINF_SHARED
+
+	IF (DIFF) THEN
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,LAST
+	   IF (IER.EQ.0) THEN
+  	      DO I=1,FOLDER_MAX
+	         DO J=1,2
+		    IF (LAST_FOLDER_NUMBER+1.EQ.I)
+     &		       LAST(J,I) = LAST_READ_BTIM(J,I)
+		    LAST_READ_BTIM(J,I) = LAST(J,I)
+	         END DO
+	      END DO
+	      REWRITE (9,IOSTAT=IER) USERNAME,LAST
+	   END IF
+	END IF
+
+	IF (DIFF1) THEN
+	   LU = TRIM(USERNAME)
+	   USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,OLD_LAST_SYS_BTIM
+	   IF (IER.EQ.0) THEN
+  	      DO I=1,FOLDER_MAX
+	         DO J=1,2
+		    IF (LAST_FOLDER_NUMBER+1.EQ.I)
+     &			  OLD_LAST_SYS_BTIM(J,I) = LAST_SYS_BTIM(J,I)
+		    LAST_SYS_BTIM(J,I) = OLD_LAST_SYS_BTIM(J,I)
+	         END DO
+	      END DO
+	      REWRITE (9,IOSTAT=IER) USERNAME,OLD_LAST_SYS_BTIM
+	   ELSE
+	      WRITE (9,IOSTAT=IER) USERNAME,LAST_SYS_BTIM
+	   END IF
+	   USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	END IF
+
+	IF (DIFF2) THEN
+	   LU = TRIM(USERNAME)
+	   USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	   IF (LU.GT.1) THEN
+	      USERNAME(LU-1:LU-1) = CHAR(128.OR.ICHAR(USERNAME(LU-1:LU-1)))
+	   ELSE
+	      USERNAME(2:2) = CHAR(128.OR.ICHAR(USERNAME(2:2)))
+	   END IF
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,OLD_LAST_NEWS_READ
+	   IF (IER.EQ.0) THEN
+  	      DO I=1,FOLDER_MAX
+	         DO J=2,1,-1
+		    IF (I.EQ.NEWS_FIND_SUBSCRIBE().OR.
+     &			OLD_LAST_NEWS_READ2(1,I).NE.LAST_NEWS_READ2(1,I))
+     &		       OLD_LAST_NEWS_READ(J,I) = LAST_NEWS_READ(J,I)
+		    LAST_NEWS_READ(J,I) = OLD_LAST_NEWS_READ(J,I)
+	         END DO
+	      END DO
+	      REWRITE (9,IOSTAT=IER) USERNAME,OLD_LAST_NEWS_READ
+	   ELSE
+	      WRITE (9,IOSTAT=IER) USERNAME,LAST_NEWS_READ
+	   END IF
+	   USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	   IF (LU.GT.1) THEN
+	      USERNAME(LU-1:LU-1) = CHAR(127.AND.ICHAR(USERNAME(LU-1:LU-1)))
+	   ELSE
+	      USERNAME(2:2) = CHAR(127.AND.ICHAR(USERNAME(2:2)))
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLINF
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION SYS_BINTIM(TIME,BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER BTIM(2)
+
+	CHARACTER*(*) TIME
+
+	CHARACTER*24 TIME1
+
+	TIME1 = TIME(FIRST_ALPHA(TIME):)
+	DO I=TRIM(TIME1),2,-1
+	   IF (TIME1(I-1:I).EQ.'  ') TIME1(I-1:) = TIME1(I:)
+	END DO
+
+	IF (TIME1.EQ.'-') TIME1 = '-- :'
+
+	IF (TRIM(TIME1).EQ.20) THEN
+	   SYS_BINTIM = SYS$BINTIM(TIME1//'.00',BTIM)
+	ELSE
+	   SYS_BINTIM = SYS$BINTIM(TIME1(:MIN(TRIM(TIME1),23)),BTIM)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEW_MESSAGE_NOTIFICATION
+C
+C  SUBROUTINE NEW_MESSAGE_NOTIFICATION
+C
+C  FUNCTION:
+C
+C  Update user's last read bulletin date.  If new bulletins have been
+C  added since the last time bulletins have been read, position bulletin
+C  pointer so that next bulletin read is the first new bulletin, and
+C  alert user.  If READNEW set and no new bulletins, just exit.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+
+	COMMON /LOGIN_BTIM/ LOGIN_BTIM_SAVE(2)
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	IF (INCMD(:4).EQ.'SHOW') THEN
+	   CALL READ_IN_FOLDERS			! Read folder info
+	ELSE IF (.NOT.LOGIN_SWITCH) THEN
+	   LOGIN_BTIM_SAVE(1) = LOGIN_BTIM(1)
+	   LOGIN_BTIM_SAVE(2) = LOGIN_BTIM(2)
+	   CALL UPDATE_READ(0)			! Update login time
+	   CALL SHOW_NEW_VERSION
+	   IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	      CALL SELECT_FOLDER(.TRUE.,IER)
+	      IF (IER) RETURN
+	   END IF
+	   CALL READ_IN_FOLDERS			! Read folder info
+	ELSE
+	   LOGIN_SWITCH = .FALSE.		! So LOGIN_FOLDER entry doesn't
+	END IF					! think it's called via LOGIN
+
+	FOLDER_Q = SAVE_FOLDER_Q1
+
+	DO I = 1,SAVE_FOLDER_NUM
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   CALL CLR2(NEW_MSG,FOLDER_NUMBER)	! Clear new message flag
+	   IF (.NOT.TEST_BULLCP().AND.NODE_AREA.GT.0.AND.READIT.EQ.1
+     &	       .AND.TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+	      CALL SET2(NEW_MSG,FOLDER_NUMBER)
+	   ELSE IF (TEST2(SET_FLAG,FOLDER_NUMBER).OR.
+     &		TEST2(BRIEF_FLAG,FOLDER_NUMBER).OR.
+     &		(FOLDER_NUMBER.GT.0.AND.
+     &		TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND.READIT.EQ.1)) THEN
+	      IF (READIT.EQ.1.AND.SYSTEM_SWITCH.AND.
+     &		TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+	         DIFF = COMPARE_BTIM(SYSTEM_LOGIN_BTIM,
+     &					F_NEWEST_BTIM)
+	      ELSE
+	         DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+		 IF (DIFF.LT.0.AND.READIT.EQ.1) THEN
+		    IF (.NOT.TEST2(BRIEF_FLAG,FOLDER_NUMBER).OR.
+     &			.NOT.TEST2(SET_FLAG,FOLDER_NUMBER).OR.
+     &			NEW_FLAG(2).NE.-1) THEN
+	               DIFF = COMPARE_BTIM(LOGIN_BTIM_SAVE,F_NEWEST_BTIM)
+		    END IF
+		    IF (FOLDER_BBOARD(:2).EQ.'::'.AND.DIFF.GE.0) THEN
+			IER = MINUTE_DIFF(LOGIN_BTIM_SAVE,F_NEWEST_BTIM)
+			IF (IER.LE.15) DIFF = -1
+		    END IF
+		 END IF
+	      END IF
+	      IF (F_NBULL.GT.0.AND.(DIFF.LT.0.OR.(READIT.EQ.1.AND.
+     &		  BTEST(FOLDER_FLAG,7)))) THEN	    ! If new unread messages
+		 CALL SET2(NEW_MSG,FOLDER_NUMBER)   ! Set new message flag
+	      END IF
+	   END IF
+	END DO
+
+	FOLDER_Q = SAVE_FOLDER_Q1
+
+	IF (READIT.EQ.0) THEN 			! If not in READNEW mode
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   NEW_MESS = .FALSE.
+	   DO I = 1,SAVE_FOLDER_NUM-1
+	      CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      IF (TEST2(NEW_MSG,FOLDER_NUMBER)) THEN
+		 DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+		 IF (DIFF.LT.0) THEN		! Are there unread messages?
+		    DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_NOSYS_BTIM)
+		    IF (DIFF.GT.0) THEN		! Unread non-system messages?
+	               DIFF = COMPARE_BTIM(LOGIN_BTIM,F_NEWEST_BTIM)
+						! No. Unread system messages?
+		       IF (DIFF.GT.0) THEN	! No, update last read time.
+			  LAST_READ_BTIM(1,FOLDER_NUMBER+1) =
+     &						F_NEWEST_BTIM(1)
+			  LAST_READ_BTIM(2,FOLDER_NUMBER+1) =
+     &						F_NEWEST_BTIM(2)
+		       END IF
+		    END IF
+		    IF (DIFF.LT.0) THEN
+		       WRITE (6,'('' There are new messages in '',
+     &			   ''folder '',A)') FOLDER(:TRIM(FOLDER))
+		       NEW_MESS = .TRUE.
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   CALL NEWS_NEW_NOTIFICATION(NEWS_MESS)
+	   IF (INCMD(:4).EQ.'SHOW') THEN
+	      SAVE_FOLDER_Q1 = 0
+	      RETURN
+	   END IF
+	   IF (NEW_MESS.OR.NEWS_MESS) THEN
+	      WRITE (6,'('' Type SELECT followed by foldername to'',
+     &			 '' read above messages.'')')
+	   END IF
+	   SAVE_FOLDER_Q1 = 0
+	   FOLDER_NUMBER = 0
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				F_NEWEST_BTIM)
+	   IF (DIFF.LT.0.AND.F_NBULL.GT.0) THEN
+	      CALL FIND_NEWEST_BULL	! See if there are new messages
+	      IF (BULL_POINT.NE.-1) THEN
+	        WRITE(6,'('' Type READ to read new '',A,'' messages.'')')
+     &		   FOLDER(:TRIM(FOLDER))
+		NEW_COUNT = F_NBULL - BULL_POINT
+		DIG = 0
+		DO WHILE (NEW_COUNT.GT.0)
+		   NEW_COUNT = NEW_COUNT / 10
+		   DIG = DIG + 1
+		END DO
+		WRITE(6,'('' There are '',I<DIG>,'' new messages.'')')
+     &			F_NBULL - BULL_POINT	! Alert user if new bulletins
+	      ELSE
+	        BULL_POINT = 0
+	        LAST_READ_BTIM(1,FOLDER_NUMBER+1) = F_NEWEST_BTIM(1)
+	        LAST_READ_BTIM(2,FOLDER_NUMBER+1) = F_NEWEST_BTIM(2)
+	      END IF
+	   END IF
+	ELSE				! READNEW mode.
+	   DO I = 1,SAVE_FOLDER_NUM
+	      CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      IF (TEST2(NEW_MSG,FOLDER_NUMBER)) THEN
+		 CALL SELECT_FOLDER(.FALSE.,IER)
+		 IF (IER) THEN
+	           IF (SYSTEM_SWITCH.AND.
+     &		        TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+	            DIFF = COMPARE_BTIM(SYSTEM_LOGIN_BTIM,F_NEWEST_BTIM)
+		   ELSE
+		    DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+		    IF (BTEST(FOLDER_FLAG,7)) DIFF = -1
+		    IF (DIFF.LT.0.AND.TEST2(BRIEF_FLAG,FOLDER_NUMBER)
+     &		       .AND.TEST2(SET_FLAG,FOLDER_NUMBER)) THEN
+		       IF (DIFF.LT.0) THEN
+		        IF (FOLDER_NUMBER.GT.0) CALL LOGIN_FOLDER
+	                IF (BULL_POINT.NE.-1.OR.NEW_FLAG(2).EQ.-1.OR.
+     &			   .NOT.TEST2(SYSTEM_FLAG,FOLDER_NUMBER))
+     &		        WRITE (6,'('' There are new messages in folder ''
+     &			  ,A)') FOLDER(:TRIM(FOLDER))
+		       ELSE
+		        WRITE (6,'('' There are new messages in folder ''
+     &			  ,A)') FOLDER(:TRIM(FOLDER))
+		       END IF
+		       DIFF = 0
+		    END IF
+		   END IF
+		   IF (DIFF.LT.0) THEN
+		    IF (FOLDER_NUMBER.GT.0) CALL LOGIN_FOLDER
+	            IF (BULL_POINT.NE.-1) THEN
+		     IF (.NOT.TEST2(BRIEF_FLAG,FOLDER_NUMBER)) THEN
+		       SAVE_BULL_POINT = BULL_POINT
+		       REDO = .TRUE.
+		       DO WHILE (REDO)
+		          REDO = .FALSE.
+		          CALL READNEW(REDO)
+			  IF (REDO) CALL REDISPLAY_DIRECTORY
+			  BULL_POINT = SAVE_BULL_POINT
+		       END DO
+		     END IF
+		    END IF
+		   END IF
+		 END IF
+	      END IF
+	   END DO
+	   CALL NEWS_NEW_NOTIFICATION(NEWS_MESS)
+	   CALL EXIT
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE READ_IN_FOLDERS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+	DATA SAVE_FOLDER_Q1/0/
+
+	COMMON /READIT/ READIT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+        COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+        COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+        COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+        CHARACTER*4 SEPARATE
+ 
+	CALL INIT_QUEUE(SAVE_FOLDER_Q1,FOLDER_COM)
+	FOLDER_Q = SAVE_FOLDER_Q1
+
+	CALL OPEN_BULLFOLDER_SHARED		! Go find folders
+
+	SAVE_FOLDER_NUM = 0
+
+	FOLDER_NUMBER = 0
+	CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+        IF (LOGIN_SWITCH) FOLDER_NAME = FOLDER
+	DO WHILE (IER.EQ.0)
+	   SAVE_FOLDER_NUM = SAVE_FOLDER_NUM + 1
+	   IF (.NOT.TEST_BULLCP().AND.NODE_AREA.GT.0.AND.READIT.EQ.1
+     &	       .AND.TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+	   ELSE IF ((NEW_FLAG(1).LT.142.OR.NEW_FLAG(1).GT.143).AND.
+     &	      TEST2(BRIEF_FLAG,FOLDER_NUMBER).AND.
+     &	      .NOT.TEST2(SET_FLAG,FOLDER_NUMBER)) THEN
+	      CALL CHANGE_FLAG_NOCMD(0,3)
+	      CALL SET_VERSION
+	   ELSE IF (TEST2(SET_FLAG,FOLDER_NUMBER).OR.
+     &		TEST2(BRIEF_FLAG,FOLDER_NUMBER).OR.
+     &		(FOLDER_NUMBER.GT.0.AND.(BTEST(FOLDER_FLAG,2).OR.
+     &		TEST2(SYSTEM_FLAG,FOLDER_NUMBER)).AND.READIT.EQ.1)) THEN
+C
+C  Unknown problem caused system folder flag in folder file to disappear
+C  so this tests to see if the flag has disappeared and resets if needed.
+C
+	      IF (TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND.
+     &		  .NOT.BTEST(FOLDER_FLAG,2)) THEN
+		 FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	         CALL REWRITE_FOLDER_FILE(IER)
+	      ELSE IF (.NOT.TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND.
+     &		  BTEST(FOLDER_FLAG,2)) THEN
+		 INQUIRE (UNIT=4,OPENED=IER)
+		 CALL MODIFY_SYSTEM_LIST(IER)
+	      END IF
+	   END IF
+	   CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   CALL READ_FOLDER_FILE_KEYNUM_GT(FOLDER_NUMBER,IER)
+	END DO
+
+	CALL CLOSE_BULLFOLDER
+
+	FOLDER_Q = SAVE_FOLDER_Q1
+	CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE DISCONNECT_REMOTE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	WRITE (6,'('' ERROR: Connection to remote folder disconnected.'')')
+
+	FOLDER_NUMBER = 0
+
+	CALL SELECT_FOLDER(.FALSE.,IER)
+
+	WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &	   FOLDER(:TRIM(FOLDER))
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin8.for b/decus/vmslt00a/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..a1955886d1d9d520232d1e6bbd1d5c26a881c3c1
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin8.for
@@ -0,0 +1,2165 @@
+C
+C  BULLETIN8.FOR, Version 10/27/94
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE START_DECNET
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /NEWSHOST/ NEWS_GOT_HOST
+
+	COMMON /LISTEN/ LISTEN_CHAN,LISTEN_IOSB(4)
+	INTEGER*2 LISTEN_IOSB
+
+	CHARACTER NAMEDESC*12 /'BULLETIN1'/
+	CHARACTER NAMEDESC1*4 /'NNTP'/
+
+	DIMENSION NFBDESC(2)
+	LOGICAL*1 NFB(5)
+
+	EXTERNAL IO$_ACPCONTROL,LISTEN_AST
+
+	PARAMETER NFB$C_DECLNAME = '15'X
+
+	IF (CONFIRM_USER('DECNET').EQ.0) THEN
+	   CALL SETDEFAULT('DECNET')
+	END IF
+
+C	CALL SET_TIMER('02')
+
+	GATEWAY_ONLY = SYS_TRNLNM('BULL_NEWS_GATEWAY_ONLY','DEFINED')
+
+	NFBDESC(1) = 5
+	NFBDESC(2) = %LOC(NFB)
+
+	NFB(1) = NFB$C_DECLNAME
+
+	NEWS_GOT_HOST = NEWS_GETHOST()
+
+	IF (.NOT.GATEWAY_ONLY) THEN
+	   IER = SYS$CREMBX(%VAL(0),MBX_CHAN,%VAL(132),%VAL(528),,,
+     &                   'BULL_MBX')
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$ASSIGN('_NET:',DCL_CHAN,,'BULL_MBX') ! Assign net device
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$QIOW(,%VAL(DCL_CHAN),IO$_ACPCONTROL,,,,
+     &		  NFBDESC,NAMEDESC(:9),,,,)
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   CALL SYS$SETAST(%VAL(0))
+	   CALL READ_MBX(DCL_CHAN)
+	   CALL SYS$SETAST(%VAL(1))
+	END IF
+
+	IF (.NOT.SYS_TRNLNM('BULL_NO_NEWS_GATEWAY','DEFINED')) THEN
+	   IER = SYS$CREMBX(%VAL(0),MBX_CHAN1,%VAL(132),%VAL(528),,,
+     &                   'BULL_MBX1')
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$ASSIGN('_NET:',DCL_CHAN1,,'BULL_MBX1')
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$QIOW(,%VAL(DCL_CHAN1),IO$_ACPCONTROL,,,,
+     &		NFBDESC,NAMEDESC1,,,,)
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   CALL SYS$SETAST(%VAL(0))
+	   CALL READ_MBX(DCL_CHAN1)
+	   CALL SYS$SETAST(%VAL(1))
+	END IF
+
+	IF (SYS_TRNLNM('BULL_TCP_NEWS_GATEWAY','DEFINED')) THEN
+	   IF (NNTP_LISTEN(LISTEN_CHAN)) THEN
+	      CALL NNTP_ACCEPT_WAIT(LISTEN_CHAN,LISTEN_AST,LISTEN_IOSB)
+	   END IF
+	END IF
+
+	IF (GATEWAY_ONLY) CALL SYS$HIBER()
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE LISTEN_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /LISTEN/ LISTEN_CHAN,LISTEN_IOSB(4)
+	INTEGER*2 LISTEN_IOSB
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	COMMON /NEWSHOST/ NEWS_GOT_HOST
+
+	EXTERNAL NEWS_SOCKET_AST
+
+	INTEGER*2 ACCEPT_IOSB(4)
+
+	IF (LISTEN_IOSB(1)) THEN
+	   IER = NNTP_ACCEPT(LISTEN_CHAN,ACCEPT_CHAN,ACCEPT_IOSB)
+	   IF (IER) THEN
+	      UNIT_INDEX = 1
+	      DO WHILE (UNIT_INDEX.LE.MAXLINK.AND.UNITS(UNIT_INDEX).NE.0)
+	          UNIT_INDEX = UNIT_INDEX + 1
+	      END DO
+	      IF (UNIT_INDEX.LE.MAXLINK) THEN
+	         COUNT = COUNT + 1
+	         DEVS(UNIT_INDEX) = ACCEPT_CHAN
+		 UNITS(UNIT_INDEX) = ACCEPT_CHAN
+	         IER = NEWS_GOT_HOST.AND.NEWS_ASSIGN()
+	         IF (IER) THEN
+	            NNTP_CHANS(UNIT_INDEX) = NEWS_GET_CHAN()
+		    WRITE_IOSB(1,UNIT_INDEX) = 1
+		    IER = NEWS_SOCKET_BULLCP(0,
+     &			WRITE_IOSB(1,UNIT_INDEX),NEWS_SOCKET_AST,UNIT_INDEX)
+		    IF (IER.EQ.-1) CALL NEWS_SOCKET_AST(%VAL(UNIT_INDEX))
+	         END IF
+	         IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	      ELSE
+	         CALL SYS$DASSGN(%VAL(ACCEPT_CHAN))
+	      END IF
+	   ELSE IF (ACCEPT_CHAN.NE.-1) THEN
+	      CALL SYS$DASSGN(%VAL(ACCEPT_CHAN)) 
+	   END IF
+ 	END IF                                   
+
+	CALL REQUEUE_NNTP_ACCEPT_WAIT()
+	
+	RETURN
+	END
+
+
+
+	SUBROUTINE REQUEUE_NNTP_ACCEPT_WAIT()
+	
+	IMPLICIT INTEGER (A-Z) 
+
+	COMMON /LISTEN/ LISTEN_CHAN,LISTEN_IOSB(4)
+	INTEGER*2 LISTEN_IOSB
+
+	EXTERNAL LISTEN_AST
+
+	CALL NNTP_ACCEPT_WAIT(LISTEN_CHAN,LISTEN_AST,LISTEN_IOSB)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SETDEFAULT(USERNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($LNMDEF)'
+
+	INCLUDE '($PSLDEF)'
+
+	INCLUDE '($UAIDEF)'
+
+	CHARACTER DEFDIR*64,DEFDEV*16,USERNAME*(*),ACCOUNT*12
+	CHARACTER SYSLOGIN*72
+
+	INTEGER*2 UIC(2)
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(LEN(DEFDEV),UAI$_DEFDEV,%LOC(DEFDEV))
+	CALL ADD_2_ITMLST(LEN(DEFDIR),UAI$_DEFDIR,%LOC(DEFDIR))
+	CALL ADD_2_ITMLST(LEN(ACCOUNT),UAI$_ACCOUNT,%LOC(ACCOUNT))
+	CALL ADD_2_ITMLST(4,UAI$_UIC,%LOC(UIC))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	CALL SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+
+	CALL SETACC(ACCOUNT)
+	CALL SETUSER(USERNAME)
+	CALL SETUIC(INT(UIC(2)),INT(UIC(1)))
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST
+     &		(ICHAR(DEFDEV(:1)),LNM$_STRING,%LOC(DEFDEV(2:)))
+	CALL END_ITMLST(CRELNM_ITMLST)	! Get address of itemlist
+
+	CALL SYS$CRELNM(,'LNM$PROCESS','SYS$DISK',PSL$C_SUPER,
+     &						%VAL(CRELNM_ITMLST))
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	SYSLOGIN = 'SYS$DISK:'//DEFDIR(2:)
+	CALL ADD_2_ITMLST
+     &		(ICHAR(DEFDIR(:1))+9,LNM$_STRING,%LOC(SYSLOGIN))
+	CALL END_ITMLST(CRELNM_ITMLST)	! Get address of itemlist
+
+	CALL SYS$CRELNM(,'LNM$PROCESS','SYS$LOGIN',PSL$C_SUPER,
+     &						%VAL(CRELNM_ITMLST))
+
+	CALL SYS$SETDDIR(DEFDIR(2:ICHAR(DEFDIR(:1))+1),,)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_MBX(DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	EXTERNAL MBX_AST
+
+	EXTERNAL IO$_READVBLK
+
+	DATA MBX_EF/0/
+
+	IF (MBX_EF.EQ.0) CALL LIB$GET_EF(MBX_EF)
+
+	IF (DCL_CHAN_NUM.EQ.DCL_CHAN) THEN
+	   MBX_CHAN_NUM = MBX_CHAN
+	ELSE
+	   MBX_CHAN_NUM = MBX_CHAN1
+	END IF
+
+	IER = SYS$QIO(%VAL(MBX_EF),%VAL(MBX_CHAN_NUM),
+     &		IO$_READVBLK,MBX_IOSB,
+     &		MBX_AST,%VAL(DCL_CHAN_NUM),MBX_BUF,%VAL(132),,,,)
+	IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	IF (.NOT.IER) CALL EXIT
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE MBX_AST(DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($MSGDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	INTEGER*2 MBXMSG,UNIT2
+
+	EQUIVALENCE (MBX_BUF(1),MBXMSG)
+
+	CHARACTER NODENAME*8,FROMNAME*12
+
+	IF (MBXMSG.EQ.MSG$_CONNECT.AND.MBX_IOSB(1)) THEN
+	   LNODE = 0
+	   DO WHILE (MBX_BUF(10+LNODE).NE.':')
+	      LNODE = LNODE + 1
+	      NODENAME(LNODE:LNODE) = CHAR(MBX_BUF(9+LNODE))
+	   END DO
+	   DO I=LNODE+1,LEN(NODENAME)
+	      NODENAME(I:I) = ' '
+	   END DO
+	   I = 10 + LNODE
+	   DO WHILE (MBX_BUF(I).NE.'=')
+	      I = I + 1
+	   END DO
+	   LUSER = 0
+	   DO WHILE (MBX_BUF(I+LUSER+1).NE.' '.AND.
+     &		     MBX_BUF(I+LUSER+1).NE.'/')
+	      LUSER = LUSER + 1
+	      USERNAME(LUSER:LUSER) = CHAR(MBX_BUF(I+LUSER))
+	   END DO
+	   DO I=LUSER+1,LEN(USERNAME)
+	      USERNAME(I:I) = ' '
+	   END DO
+	   FROMNAME = USERNAME
+	   CALL GET_PROXY_USERNAME(NODENAME,USERNAME)
+	   CALL BULL_CONNECT(NODENAME,USERNAME,FROMNAME,%LOC(DCL_CHAN_NUM))
+	ELSE IF ((MBXMSG.EQ.MSG$_INTMSG.OR.MBXMSG.EQ.MSG$_REJECT.OR.
+     &		 MBXMSG.EQ.MSG$_CONFIRM).AND.MBX_IOSB(1)) THEN
+	   CALL READ_MBX(%LOC(DCL_CHAN_NUM))
+	ELSE
+ 	   CALL LIB$MOVC3(2,MBX_BUF(3),UNIT2)
+	   UNIT_INDEX = 1
+	   DO WHILE (UNIT_INDEX.LE.MAXLINK.AND.UNITS(UNIT_INDEX).NE.UNIT2)
+	      UNIT_INDEX = UNIT_INDEX + 1
+	   END DO
+	   IF (UNIT_INDEX.LE.MAXLINK) CALL DISCONNECT(UNIT_INDEX)
+ 	   CALL READ_MBX(%LOC(DCL_CHAN_NUM))
+	END IF
+
+	RETURN
+ 	END
+
+
+
+
+	SUBROUTINE READ_CHAN(CHAN,UNIT_INDEX)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	EXTERNAL READ_AST
+
+	EXTERNAL IO$_READVBLK
+
+	IER = SYS$QIO(,%VAL(CHAN),IO$_READVBLK,
+     &	   READ_IOSB(1,UNIT_INDEX),READ_AST,
+     &	   %VAL(UNIT_INDEX),READ_BUF(1,UNIT_INDEX),%VAL(1024),,,,)
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE WRITE_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	CHARACTER*128 INPUT
+
+	EXTERNAL IO$_READVBLK,NEWS_READ_AST
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (.NOT.WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   CALL DISCONNECT(UNIT_INDEX)
+	ELSE IF (LEN_SAVE(UNIT_INDEX).GT.0) THEN
+	   LEN_SAVE(UNIT_INDEX) = LEN_SAVE(UNIT_INDEX) - 1
+	   IF (LEN_SAVE(UNIT_INDEX).EQ.0) THEN
+	      IF (REC_SAVE(UNIT_INDEX).EQ.128) THEN
+	         REC_SAVE(UNIT_INDEX) = 0
+	      ELSE
+	         RETURN
+	      END IF
+	   ELSE
+              CALL READ_QUEUE(%VAL(OUT_SAVE(UNIT_INDEX)),
+     &		OUT_SAVE(UNIT_INDEX),INPUT)
+	   END IF
+	   CALL WRITE_CHAN(REC_SAVE(UNIT_INDEX),INPUT,UNIT_INDEX,IER)
+	ELSE IF (NNTP_CHANS(UNIT_INDEX).NE.0) THEN
+	   IER = SYS$QIO(,%VAL(NNTP_CHANS(UNIT_INDEX)),
+     &	      IO$_READVBLK,WRITE_IOSB(1,UNIT_INDEX),NEWS_READ_AST,
+     &	      %VAL(UNIT_INDEX),WRITE_BUF(1,UNIT_INDEX),
+     &	      %VAL(1024),,,,)
+	   IF (IER.AND.WRITE_IOSB(1,UNIT_INDEX).NE.0) THEN
+	      IER = WRITE_IOSB(1,UNIT_INDEX)
+	   END IF
+	   IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /ACTIVITY/ IO(MAXLINK),IO_SAVE(MAXLINK)
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	EXTERNAL NEWS_WRITE_AST
+
+	EXTERNAL IO$_WRITEVBLK
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (.NOT.READ_IOSB(1,UNIT_INDEX)) RETURN
+
+C	IO(UNIT_INDEX) = IO(UNIT_INDEX) + 1
+
+	CALL LIB$MOVC3(4,READ_BUF(1,UNIT_INDEX),CMD_TYPE)
+
+	IF ((CMD_TYPE.LT.1.OR.CMD_TYPE.GT.16).AND.
+     &	    READ_IOSB(2,UNIT_INDEX).EQ.0) THEN
+	   CALL DISCONNECT(UNIT_INDEX)
+	ELSE IF (CMD_TYPE.LT.1.OR.CMD_TYPE.GT.16) THEN
+	   CALL NEWS_SET_CHAN(NNTP_CHANS(UNIT_INDEX))
+	   IER = NEWS_WRITE_PACKET_BULLCP(0,
+     &			READ_IOSB(1,UNIT_INDEX),NEWS_WRITE_AST,UNIT_INDEX,
+     &			READ_BUF(1,UNIT_INDEX),READ_IOSB(2,UNIT_INDEX))
+	   IF (IER.AND.READ_IOSB(1,UNIT_INDEX).NE.0) THEN
+	      IER = READ_IOSB(1,UNIT_INDEX)
+	   END IF
+	   IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	ELSE
+	   CALL EXECUTE_COMMAND(UNIT_INDEX)
+	   CALL READ_CHAN(DEVS(UNIT_INDEX),UNIT_INDEX)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE NEWS_WRITE_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (READ_IOSB(1,UNIT_INDEX)) THEN
+	   CALL READ_CHAN(DEVS(UNIT_INDEX),UNIT_INDEX)
+	   RETURN
+	END IF
+
+	CALL DISCONNECT(UNIT_INDEX)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS_READ_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   NUM = WRITE_IOSB(2,UNIT_INDEX)
+	   IF (NUM.GT.0) THEN
+	      CALL WRITE_CHAN_BUF(NUM,UNIT_INDEX,IER)
+	      IF (IER) RETURN
+	   END IF
+	END IF
+
+	CALL DISCONNECT(UNIT_INDEX)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE WRITE_CHAN(NUM,OUTPUT,UNIT_INDEX,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	CHARACTER*(*) OUTPUT
+
+	EXTERNAL IO$_WRITEVBLK, WRITE_AST
+
+	CALL LIB$MOVC3(NUM,%REF(OUTPUT),WRITE_BUF(1,UNIT_INDEX))
+
+	ENTRY WRITE_CHAN_BUF(NUM,UNIT_INDEX,IER)
+
+	IER = SYS$QIO(,%VAL(DEVS(UNIT_INDEX)),
+     &	   IO$_WRITEVBLK,WRITE_IOSB(1,UNIT_INDEX),WRITE_AST,
+     &	   %VAL(UNIT_INDEX),WRITE_BUF(1,UNIT_INDEX),%VAL(NUM),,,,)
+
+	IF (IER.AND.WRITE_IOSB(1,UNIT_INDEX).NE.0) THEN
+	   IER = WRITE_IOSB(1,UNIT_INDEX)
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE BULL_CONNECT(NODENAME,USERNAME,FROMNAME,DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	CHARACTER*(*) USERNAME,FROMNAME
+
+	COMMON /NEWSHOST/ NEWS_GOT_HOST
+
+	EXTERNAL IO$_ACCESS,IO$M_ABORT,NEWS_SOCKET_AST
+	
+	IO_REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+
+	CALL CONNECT_ACCEPT(REJECT,CHAN,UNIT_INDEX,
+     &		NODENAME,USERNAME,FROMNAME,DCL_CHAN_NUM)
+
+	IF (REJECT.NE.IO_REJECT) THEN
+	   IF (DCL_CHAN_NUM.NE.DCL_CHAN) THEN
+	      IER = NEWS_GOT_HOST.AND.NEWS_ASSIGN()
+	      IF (IER) THEN
+	         NNTP_CHANS(UNIT_INDEX) = NEWS_GET_CHAN()
+		 WRITE_IOSB(1,UNIT_INDEX) = 1
+		 IER = NEWS_SOCKET_BULLCP(0,
+     &			WRITE_IOSB(1,UNIT_INDEX),NEWS_SOCKET_AST,UNIT_INDEX)
+		 IF (IER.EQ.-1) CALL NEWS_SOCKET_AST(%VAL(UNIT_INDEX))
+	      END IF
+	      IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	   ELSE
+	      CALL READ_CHAN(CHAN,UNIT_INDEX)
+	   END IF
+	END IF
+
+	CALL READ_MBX(DCL_CHAN_NUM)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_SOCKET_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	EXTERNAL NEWS_CREATE_AST
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   CALL NEWS_SET_CHAN(NNTP_CHANS(UNIT_INDEX))
+	   IER = NEWS_CREATE_BULLCP(0,
+     &			WRITE_IOSB(1,UNIT_INDEX),NEWS_CREATE_AST,UNIT_INDEX)
+	   IF (IER) RETURN
+	END IF
+
+	CALL DISCONNECT(UNIT_INDEX)
+
+	RETURN
+	END
+
+
+ 
+	SUBROUTINE NEWS_CREATE_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   CALL WRITE_AST(%VAL(UNIT_INDEX))
+	   CALL READ_CHAN(DEVS(UNIT_INDEX),UNIT_INDEX)
+	ELSE
+	   CALL DISCONNECT(UNIT_INDEX)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONNECT_ACCEPT(REJECT,CHAN,UNIT_INDEX,
+     &		NODENAME,USERNAME,FROMNAME,DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+	DATA COUNT /0/
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	EXTERNAL IO$_ACCESS,IO$M_ABORT
+
+	CHARACTER*(*) USERNAME,FROMNAME,NODENAME
+
+	CHARACTER*100 NCBDESC
+
+	START_NCB = 7+MBX_BUF(5)
+
+	LEN_NCB = MBX_BUF(START_NCB-1)
+
+	CALL LIB$MOVC3(LEN_NCB,MBX_BUF(START_NCB),%REF(NCBDESC))
+
+	IF (COUNT.GT.MAXLINK) THEN
+	   REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+	   CHAN = DCL_CHAN_NUM
+	ELSE
+	   IF (DCL_CHAN_NUM.EQ.DCL_CHAN) THEN
+	      IER = SYS$ASSIGN('_NET:',DEV_CHAN,,'BULL_MBX')
+	   ELSE
+	      IER = SYS$ASSIGN('_NET:',DEV_CHAN,,'BULL_MBX1')
+	   END IF
+
+	   IF (IER) CALL GETDEVUNIT(DEV_CHAN,DEV_UNIT,IER)
+
+	   IF (IER) THEN
+	      CHAN = DEV_CHAN
+	      REJECT = %LOC(IO$_ACCESS)
+
+	      UNIT_INDEX = 1
+	      DO WHILE (UNIT_INDEX.LE.MAXLINK.AND.UNITS(UNIT_INDEX).NE.0)
+	          UNIT_INDEX = UNIT_INDEX + 1
+	      END DO
+	   ELSE
+	      CALL SYS$DASSGN(%VAL(DEV_CHAN))
+	   END IF
+
+	   IF (.NOT.IER.OR.UNIT_INDEX.GT.MAXLINK) THEN
+	      REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+	      CHAN = DCL_CHAN_NUM
+	   ELSE
+	      COUNT = COUNT + 1
+	      UNITS(UNIT_INDEX) = DEV_UNIT
+	      DEVS(UNIT_INDEX) = DEV_CHAN
+	      USER_SAVE(UNIT_INDEX) = USERNAME
+	      FROM_SAVE(UNIT_INDEX) = FROMNAME
+	      NODE_SAVE(UNIT_INDEX) = NODENAME
+	      FOLDER_NUM(UNIT_INDEX) = -1
+	      LEN_SAVE(UNIT_INDEX) = 0
+	      PRIV_SAVE(1,UNIT_INDEX) = 0
+	      PRIV_SAVE(2,UNIT_INDEX) = 0
+	   END IF
+	END IF
+
+	IER = SYS$QIOW(,%VAL(CHAN),%VAL(REJECT),MBX_IOSB,,,
+     &		,NCBDESC(:LEN_NCB),,,,)
+
+	IF (REJECT.EQ.%LOC(IO$_ACCESS).AND.
+     &		(.NOT.IER.OR..NOT.MBX_IOSB(1))) THEN
+	   REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+	   COUNT = COUNT - 1
+	   DEVS(UNIT_INDEX) = 0
+	   UNITS(UNIT_INDEX) = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETDEVUNIT(CHAN,DEV_UNIT,IER)
+C
+C  SUBROUTINE GETDEVUNIT
+C
+C  FUNCTION:
+C	To get device unit number
+C  INPUT:
+C	CHAN - Channel number
+C  OUTPUT:
+C	DEV_UNIT - Device unit number
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($DVIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,DVI$_UNIT,%LOC(DEV_UNIT))
+	CALL END_ITMLST(GETDVI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETDVIW(,%VAL(CHAN),,%VAL(GETDVI_ITMLST),,,,)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETDEVNAME(CHAN,DEV_NAME,DLEN,IER)
+C
+C  SUBROUTINE GETDEVMAME
+C
+C  FUNCTION:
+C	To get device name
+C  INPUT:
+C	CHAN - Channel number
+C  OUTPUT:
+C	DEV_NAME - Device name
+C	DLEN - Length of device name
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($DVIDEF)'
+
+	CHARACTER*(*) DEV_NAME
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(DEV_NAME),DVI$_DEVNAM,%LOC(DEV_NAME),%LOC(DLEN))
+	CALL END_ITMLST(GETDVI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETDVIW(,%VAL(CHAN),,%VAL(GETDVI_ITMLST),,,,)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DISCONNECT(UNIT_INDEX)
+C
+C  SUBROUTINE DISCONNECT
+C
+C  FUNCTION: Disconnects channel and remove its entry from the lists.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	IF (UNITS(UNIT_INDEX).EQ.0) RETURN
+
+	CALL SYS$DASSGN(%VAL(DEVS(UNIT_INDEX)))
+
+	IF (NNTP_CHANS(UNIT_INDEX).EQ.0) THEN
+	   CALL UPDATE_REMOTE_USERINFO(UNIT_INDEX)
+	END IF
+
+	COUNT = COUNT - 1
+	DEVS(UNIT_INDEX) = 0
+	UNITS(UNIT_INDEX) = 0
+
+	IF (NNTP_CHANS(UNIT_INDEX).NE.0) THEN
+	   CALL NEWS_SET_CHAN(NNTP_CHANS(UNIT_INDEX))
+	   CALL NEWS_DISCONNECT
+	   NNTP_CHANS(UNIT_INDEX) = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_TIMER(MIN)
+C
+C SUBROUTINE SET_TIMER
+C
+C FUNCTION: Wakes up every MIN minutes to check for idle connections
+C
+	IMPLICIT INTEGER (A-Z)
+	INTEGER TIMADR(2)			! Buffer containing time
+						! in desired system format.
+	CHARACTER MIN*(*)
+
+	EXTERNAL CHECK_CONNECTIONS
+
+	CALL LIB$GET_EF(WAITEFN)
+
+	IER=SYS$BINTIM('0 00:'//MIN//':00.00',TIMADR)
+
+	ENTRY RESET_TIMER
+
+	IER=SYS$SETIMR(%VAL(WAITEFN),TIMADR,CHECK_CONNECTIONS,)
+						! Set timer.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CHECK_CONNECTIONS
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /ACTIVITY/ IO(MAXLINK),IO_SAVE(MAXLINK)
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	IF (COUNT.GT.0) THEN
+	   DO UNIT_INDEX=1,MAXLINK
+	      IF (DEVS(UNIT_INDEX).NE.0.AND.
+     &		IO(UNIT_INDEX).EQ.IO_SAVE(UNIT_INDEX)) THEN
+	         CALL DISCONNECT(UNIT_INDEX)
+	      END IF
+	   END DO
+	END IF
+
+	CALL RESET_TIMER
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_USER_PRIV(USERNAME,PRIV)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION PRIV(2)
+
+	CHARACTER USERNAME*(*)
+
+	INCLUDE '($UAIDEF)'
+
+	INTEGER*2 UIC(2)
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(8,UAI$_PRIV,%LOC(PRIV))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+
+	IF (.NOT.IER) THEN
+	   USERNAME = 'DECNET'
+	   IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_PROXY_USERNAME(NODE,USERNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER NODE*(*),USERNAME*(*)
+
+	CHARACTER NETUAF*100,USERTEMP*12
+
+	COMMON /NETUAF/ NETUAF_QUEUE,NETUAF_NUM
+
+	LNODE = LEN(NODE)
+	LUSER = LEN(USERNAME)
+
+	NUM = 1
+	NENTRY = NETUAF_QUEUE
+
+	USERTEMP = 'DECNET'
+
+	DO WHILE (NUM.LE.NETUAF_NUM)
+	   NUM = NUM + 1
+	   CALL READ_QUEUE(%VAL(NENTRY),NENTRY,NETUAF)
+	   IF ((NETUAF(:1).EQ.'*'.OR.NETUAF(:LNODE).EQ.NODE).AND.
+     &	       (NETUAF(33:32+LUSER).EQ.USERNAME.OR.
+     &	       NETUAF(65:65).EQ.'*')) THEN
+	      IF (NETUAF(33:32+LUSER).EQ.USERNAME) THEN
+	         IF (NETUAF(65:65).NE.'*') USERNAME = NETUAF(65:)
+	         RETURN
+	      END IF
+	      IF (NETUAF(65:65).NE.'*') THEN
+		 USERTEMP = NETUAF(65:)
+	      ELSE
+	         USERTEMP = USERNAME
+	      END IF
+	   END IF
+	END DO
+
+	USERNAME = USERTEMP
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_PROXY_ACCOUNTS
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER NETUAF*656
+
+	COMMON /NETUAF/ NETUAF_QUEUE,NETUAF_NUM
+	DATA NETUAF_QUEUE/0/
+
+	CALL INIT_QUEUE(NETUAF_QUEUE,NETUAF(:100))
+
+	OPEN (UNIT=7,FILE='NETPROXY',DEFAULTFILE='SYS$SYSTEM:NETPROXY.DAT',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+
+	FORMAT = 0
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=7,FILE='NETUAF',DEFAULTFILE='SYS$SYSTEM:NETUAF.DAT',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+	   FORMAT = 1
+	END IF
+
+	NETUAF_NUM = 0
+	NENTRY = NETUAF_QUEUE
+	DO WHILE (IER.EQ.0)
+	   READ (7,'(Q,A)',IOSTAT=IER) NLEN,NETUAF
+	   IF (IER.EQ.0) THEN
+	      NETUAF_NUM = NETUAF_NUM + 1
+	      IF (FORMAT.EQ.0) THEN
+		 NETUAF = NETUAF(13:)
+		 NLEN = NLEN - 12
+		 DO WHILE (NETUAF(67:67).NE.CHAR(1).AND.NLEN.GT.64)
+		    SKIP = 4 + ICHAR(NETUAF(65:65))
+		    NETUAF(65:) = NETUAF(65+SKIP:)
+		    NLEN = NLEN - SKIP
+		 END DO
+		 IF (NLEN.GT.64) THEN
+		    ULEN = ICHAR(NETUAF(65:65))
+		    NETUAF(65:) = NETUAF(69:)
+		    DO I=65+ULEN,76
+		       NETUAF(I:I) = ' '
+		    END DO
+		 ELSE
+		    NETUAF(65:) = 'DECNET'
+		 END IF
+	      END IF
+              CALL WRITE_QUEUE(%VAL(NENTRY),NENTRY,NETUAF(:100))
+	   END IF
+	END DO
+
+	CLOSE (UNIT=7)
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE EXECUTE_COMMAND(UNIT_INDEX)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+        INCLUDE 'BULLFILES.INC'
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BROAD_MESSAGE/ BMESSAGE,BLENGTH
+
+	PARAMETER BRDCST_LIMIT = 82*12 + 2 +2
+	CHARACTER*(BRDCST_LIMIT) BMESSAGE
+
+        COMMON /MAIN_FOLDER_DIRECTORY/ FOLDER1_DIRECTORY
+        CHARACTER*80 FOLDER1_DIRECTORY
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+        CHARACTER*80 FOLDER2_DIRECTORY
+
+	DIMENSION SCRATCH(MAXLINK),OUT_HEAD(MAXLINK)
+	DATA SCRATCH/MAXLINK*0/,OUT_HEAD/MAXLINK*0/
+
+	EXTERNAL SS$_NOSUCHNODE,SS$_NOSUCHOBJ
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER BUFFER*(FOLDER_RECORD+16),DESCRIP_TEMP*56
+	CHARACTER NODENAME*8,BULLCP_USER*12,INQUEUE*128
+
+	EQUIVALENCE (BUFFER,CMD_TYPE),(BUFFER,INQUEUE)
+
+	INTEGER BULLCP_PRIV(2)
+
+	CALL COPY2(BULLCP_PRIV,PROCPRIV)
+
+	ILEN = READ_IOSB(2,UNIT_INDEX)
+	CALL LIB$MOVC3(ILEN,READ_BUF(1,UNIT_INDEX),%REF(BUFFER))
+
+	REMOTE_SET = .FALSE.
+	REC_SAVE(UNIT_INDEX) = 0
+	USERNAME = USER_SAVE(UNIT_INDEX)
+	FOLDER = FOLDERNAME(UNIT_INDEX)
+	FOLDER_NUMBER = FOLDER_NUM(UNIT_INDEX)
+	FOLDER_FLAG = 0
+	NODENAME = NODE_SAVE(UNIT_INDEX)
+	CALL COPY2(PROCPRIV,PRIV_SAVE(1,UNIT_INDEX))
+
+	CALL INIT_QUEUE(OUT_HEAD(UNIT_INDEX),INQUEUE)
+
+	IF (CMD_TYPE.EQ.3.OR.CMD_TYPE.EQ.4.OR.(CMD_TYPE.GE.9.AND.
+     &	    CMD_TYPE.LE.11).OR.CMD_TYPE.EQ.15.OR.CMD_TYPE.EQ.1) THEN
+						! Do we need priv info?
+	   IF (PROCPRIV(1).EQ.0.AND.PROCPRIV(2).EQ.0) THEN
+	      CALL GET_USER_PRIV(USER_SAVE(UNIT_INDEX),
+     &		 PRIV_SAVE(1,UNIT_INDEX))
+	      USERNAME = USER_SAVE(UNIT_INDEX)	! If changed to DECNET
+	      CALL COPY2(PROCPRIV,PRIV_SAVE(1,UNIT_INDEX))
+	      IF ( (PROCPRIV(1).AND.NEEDPRIV(1)).EQ.0.AND.
+     &		   (PROCPRIV(2).AND.NEEDPRIV(2)).EQ.0) THEN
+		 CALL CHECK_BULLETIN_PRIV(USERNAME)
+		 CALL COPY2(PRIV_SAVE(1,UNIT_INDEX),PROCPRIV)
+	      END IF
+	   END IF
+	END IF
+
+	FOLDER2_DIRECTORY = FOLDER_DIRECTORY
+	IF (FOLDER_DIRECTORY.NE.FOLDER1_DIRECTORY.AND.
+     &		TRIM(FOLDER1_DIRECTORY).GT.0) THEN
+	   FOLDER_DIRECTORY = FOLDER1_DIRECTORY
+	   CALL ADD_DIRECTORIES
+	END IF
+
+	IF (CMD_TYPE.EQ.1.AND.BUFFER(ILEN:ILEN).EQ.'?') THEN
+	   IF (BUFFER(5:ILEN).EQ.'SYSTEM?') THEN
+	      CALL LIB$MOVC3(4,1,%REF(BUFFER(1:)))
+	      CALL WRITE_CHAN(4,BUFFER,UNIT_INDEX,IER1)
+	   ELSE 
+	      CALL LIB$MOVC3(4,0,%REF(BUFFER(1:)))
+	      CALL WRITE_CHAN(4,BUFFER,UNIT_INDEX,IER1)
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.1) THEN			! Select folder
+	   IF (BUFFER(ILEN:ILEN).EQ.'+') THEN
+	      SYSLOG = .TRUE.
+	      ILEN = ILEN - 1
+	   ELSE 
+	      SYSLOG = .FALSE.
+	   END IF
+	   FOLDER1 = BUFFER(5:ILEN)
+	   FOLDER_NUMBER = -2
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL LIB$MOVC3(4,IER,%REF(BUFFER(1:)))
+	   CALL LIB$MOVC3(4,READ_ONLY,%REF(BUFFER(5:)))
+	   IF (USERNAME.NE.'DECNET'.AND.IER) THEN
+	      CALL OPEN_USERINFO
+	      IF (USERNAME.EQ.'DECNET') THEN	! User wasn't real.
+	       USER_SAVE(UNIT_INDEX) = USERNAME
+	       CALL LIB$MOVC3(4,0,%REF(BUFFER(9:)))
+	       CALL LIB$MOVC3(4,0,%REF(BUFFER(13:)))
+	      ELSE
+	       CALL LIB$MOVC3(8,LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				%REF(BUFFER(9:)))
+	       LAST_SAVE(1,UNIT_INDEX) = LAST_READ_BTIM(1,FOLDER_NUMBER+1)
+	       LAST_SAVE(2,UNIT_INDEX) = LAST_READ_BTIM(2,FOLDER_NUMBER+1)
+	      END IF
+	   ELSE
+	      CALL LIB$MOVC3(4,0,%REF(BUFFER(9:)))
+	      CALL LIB$MOVC3(4,0,%REF(BUFFER(13:)))
+	   END IF
+	   LINFO = 16
+	   IF (SYSLOG) THEN
+	      LINFO = 24
+	      CALL LIB$MOVC3(8,LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &			       LAST_SYS_SAVE(1,UNIT_INDEX))
+	      CALL LIB$MOVC3(8,LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &				%REF(BUFFER(17:)))
+	      IF (LAST_SYS_SAVE(1,UNIT_INDEX).EQ.0) THEN
+	         CALL LIB$MOVC3(8,LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				  LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	      END IF
+	   END IF
+	   BUFFER = BUFFER(:LINFO)//FOLDER_COM
+	   CALL WRITE_CHAN(LINFO+LEN(FOLDER_COM),BUFFER,UNIT_INDEX,IER1)
+	   IF (IER.AND.IER1) THEN
+	      IF (SYSLOG) THEN
+		 CALL SAVE_LAST_SYS_BTIM(UNIT_INDEX)
+	      ELSE
+		 LAST_SYS_SAVE(1,UNIT_INDEX) = 0
+		 LAST_SYS_SAVE(2,UNIT_INDEX) = 0
+	      END IF
+	      FOLDERNAME(UNIT_INDEX) = FOLDER
+	      FOLDER_NUM(UNIT_INDEX) = FOLDER_NUMBER
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.2) THEN		! Add message
+	   LEN_SAVE(UNIT_INDEX) = 0
+	   OUT_SAVE(UNIT_INDEX) = OUT_HEAD(UNIT_INDEX)
+	ELSE IF (CMD_TYPE.EQ.6) THEN		! Add message line
+	   LEN_SAVE(UNIT_INDEX) = LEN_SAVE(UNIT_INDEX) + 1
+	   CALL WRITE_QUEUE(%VAL(OUT_SAVE(UNIT_INDEX)),
+     &			OUT_SAVE(UNIT_INDEX),BUFFER(5:132))
+	ELSE IF (CMD_TYPE.EQ.3) THEN		! Add message entry
+	   FROM = USER_SAVE(UNIT_INDEX)
+	   IF (FROM.EQ.'DECNET') FROM = FROM_SAVE(UNIT_INDEX)
+	   CALL LIB$MOVC3(56,%REF(BUFFER(5:)),%REF(DESCRIP))
+	   P = LEN(DESCRIP) + 5
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXDATE))
+	   P = LEN(EXDATE) + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXTIME))
+	   P = LEN(EXTIME) + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),SYSTEM)
+	   P = 4 + P
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   IF (READ_ONLY.AND.
+     &		FOLDER_OWNER.NE.USERNAME.AND..NOT.SETPRV_PRIV()) THEN
+	      BUFFER = 'ERROR: Insufficient privileges to add message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   ELSE IF ((SYSTEM.AND.7).NE.0) THEN
+	      IF (FOLDER_NUMBER.GT.0.AND.IBCLR(SYSTEM,1).NE.0.AND.
+     &			.NOT.BTEST(FOLDER_FLAG,2)) THEN	! Test if SYSTEM folder
+		 SYSTEM = SYSTEM.AND.2
+	         CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      END IF
+	      IF ((SYSTEM.AND.7).NE.0.AND..NOT.SETPRV_PRIV()) THEN
+							! Priv test
+	         IF (F_EXPIRE_LIMIT.GT.0.AND..NOT.  ! Expiration limit present
+     &		     FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	            SYSTEM = 0
+	            CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+		 ELSE					! Allow permanent if
+		    SYSTEM = SYSTEM.AND.2		! owner of folder
+	         END IF
+	      END IF
+	      IF (BTEST(SYSTEM,2)) THEN			! Shutdown?
+	         CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	         WRITE (EXTIME,'(I4)') NODE_NUMBER
+	         WRITE (EXTIME(7:),'(I4)') NODE_AREA
+	         DO I=1,11
+		    IF (EXTIME(I:I).EQ.' ') EXTIME(I:I) = '0'
+	         END DO
+	         EXTIME = EXTIME(1:2)//':'//EXTIME(3:4)//':'//
+     &			 EXTIME(7:8)//'.'//EXTIME(9:10)
+	      END IF
+	   END IF
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),BROAD)
+	   P = 4 + P
+	   IF (BROAD.AND..NOT.SETPRV_PRIV().AND..NOT.OPER_PRIV()) THEN
+	      BROAD = 0
+	   END IF
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),BELL)
+	   P = 4 + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),ALL)
+	   P = 4 + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),CLUSTER)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(0,IER)			! Get NBLOCK
+	   IF (IER.EQ.0) NBLOCK = 0		! If new file, NBLOCK is 0
+	   CALL OPEN_BULLFIL
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   LENGTH = LEN_SAVE(UNIT_INDEX)
+	   LEN_SAVE(UNIT_INDEX) = 0
+	   DO I=1,LENGTH
+	      CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	      WRITE (1'NBLOCK+I) INQUEUE
+	   END DO
+	   IF (BROAD) THEN
+	      CALL GET_BROADCAST_MESSAGE(BELL)
+	      CALL BROADCAST(ALL,CLUSTER)
+	   END IF
+	   CALL CLOSE_BULLFIL			! Finished adding bulletin
+	   IF (BTEST(FOLDER_FLAG,14)) FROM = 'ANONYMOUS'
+	   CALL ADD_ENTRY			! Add the new directory entry
+	   CALL UPDATE_FOLDER			! Update info in folder file
+	   CALL CLOSE_BULLDIR			! Totally finished with add
+	   IF (NEWS_FEED()) THEN 
+	      BULL_POINT = NBULL
+	      INCMD = 'COPY/ORIGINAL/LOCAL '//
+     &			FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,'<')+1
+     &			:INDEX(FOLDER_DESCRIP,'>')-1)
+	      CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL MOVE(.FALSE.)
+	   END IF
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+
+	   CALL SAVE_LAST_READ_BTIM(UNIT_INDEX)
+
+	   IF (.NOT.BROAD) GO TO 1000
+
+100	   CALL GETUSER(BULLCP_USER)		! Get present username
+	   CALL OPEN_BULLUSER_SHARED		! Broadcast on other nodes
+	   TEMP_USER = ':'
+	   DO WHILE (TEMP_USER(:1).EQ.':')
+	      DO WHILE (REC_LOCK(IER))		 
+	         READ (4,KEYGT=TEMP_USER,IOSTAT=IER)
+     &		   TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+		 TEMP_USER = TEMP_USER(:TRIM(TEMP_USER))
+		 IF (IER.EQ.0.AND.
+     &		     (TEMP_USER(2:TRIM(TEMP_USER)).EQ.NODENAME
+     &		     .OR..NOT.TEST2(NEW_FLAG,FOLDER_NUMBER))
+     &		     .AND.TEMP_USER(:1).EQ.':') THEN
+		    IER1 = REC_LOCK(IER)	! Skip the node that
+		 END IF				! originated the message
+	      END DO
+	      IF (TEMP_USER(:1).NE.':') THEN
+		 CALL CLOSE_BULLUSER
+		 CALL SETUSER(BULLCP_USER)
+		 REMOTE_SET = .FALSE.
+	         CLOSE (UNIT=REMOTE_UNIT)
+		 GO TO 1000
+	      END IF
+	      CALL SETUSER(USERNAME)		! Reset to original username
+	      FOLDER1 = 'GENERAL'
+	      FOLDER1_BBOARD = ':'//TEMP_USER
+	      CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      IF (IER.NE.0) THEN
+		 CALL ERRSNS(IDUMMY,IDUMMY,INODE)
+	         IF (INODE.EQ.%LOC(SS$_NOSUCHNODE).OR.
+     &		     INODE.EQ.%LOC(SS$_NOSUCHOBJ).OR.INODE.EQ.0) THEN
+		    DELETE (4)
+		 END IF
+	      ELSE
+		 IER = 0
+		 I = 1
+		 DO WHILE (IER.EQ.0.AND.I.LT.BLENGTH)
+		    WRITE (REMOTE_UNIT,'(4A)',IOSTAT=IER)
+     &			15,-1,I,BMESSAGE(I:MIN(BLENGTH,I+127))
+		    I = I + 128
+		 END DO
+		 IF (IER.EQ.0) WRITE (REMOTE_UNIT,'(5A)',IOSTAT=IER)
+     &			15,BLENGTH,BELL,ALL,CLUSTER
+	      END IF
+	   END DO
+	ELSE IF (CMD_TYPE.EQ.8) THEN		! Read directory entry
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),ICOUNT)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR_SHARED
+	   IF (ICOUNT.GE.0) THEN
+	      CALL READDIR(ICOUNT,IER)
+	   ELSE
+	      CALL LIB$MOVC3(8,%REF(BUFFER(9:)),%REF(MSG_KEY(1:)))
+	      CALL READDIR_KEYGE(IER)
+	   END IF
+	   CALL CLOSE_BULLDIR
+	   CALL LIB$MOVC3(4,IER,%REF(BUFFER(1:)))
+	   IF (ICOUNT.NE.0) THEN
+	      BUFFER(5:) = BULLDIR_ENTRY
+	      CALL WRITE_CHAN
+     &		(LEN(BULLDIR_ENTRY)+4,BUFFER,UNIT_INDEX,IER)
+	   ELSE
+	      BUFFER(5:) = BULLDIR_HEADER
+	      CALL WRITE_CHAN
+     &		(LEN(BULLDIR_HEADER)+4,BUFFER,UNIT_INDEX,IER)
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.13) THEN		! Read directory entry
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),SBULL)
+	   CALL LIB$MOVC3(4,%REF(BUFFER(9:)),EBULL)
+	   CALL SET_FOLDER_FILE(0)
+  	   CALL OPEN_BULLDIR_SHARED
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   DO I=SBULL,EBULL,ISIGN(1,EBULL-SBULL)
+	      CALL READDIR(I,IER)
+	      INQUEUE = BULLDIR_ENTRY
+              CALL WRITE_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   END DO
+	   CALL CLOSE_BULLDIR
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   REC_SAVE(UNIT_INDEX) = LEN(BULLDIR_ENTRY)
+	   LEN_SAVE(UNIT_INDEX) = ABS(EBULL - SBULL) + 1
+           CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   OUT_SAVE(UNIT_INDEX) = OENTRY
+	   CALL WRITE_CHAN(REC_SAVE(UNIT_INDEX),INQUEUE,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.9) THEN		! Write directory entry
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),ICOUNT)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR
+	   IF (ICOUNT.GT.0) THEN
+	      BULLDIR_ENTRY = BUFFER(9:)
+	      CALL WRITEDIR_NOCONV(ICOUNT,IER)
+	   ELSE
+	      BULLDIR_HEADER = BUFFER(9:)
+	      CALL WRITEDIR_NOCONV(ICOUNT,IER)
+	   END IF
+	   CALL CLOSE_BULLDIR
+	ELSE IF (CMD_TYPE.EQ.4) THEN
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),BULL_DELETE)
+	   CALL LIB$MOVC3(4,%REF(BUFFER(9:)),IMMEDIATE)
+	   DESCRIP_TEMP = BUFFER(13:ILEN)
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(BULL_DELETE,IER)
+	   IF (IER.EQ.BULL_DELETE.OR.DESCRIP.NE.DESCRIP_TEMP) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Cannot find message to delete.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   ELSE IF (USERNAME.NE.FROM.AND.FROM_SAVE(UNIT_INDEX).NE.FROM
+     &	    .AND.FOLDER_OWNER.NE.USERNAME.AND..NOT.SETPRV_PRIV()) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Insufficient privileges to delete message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL REMOVE_ENTRY
+     &		(BULL_DELETE,BULL_DELETE,BULL_DELETE,IMMEDIATE)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.5) THEN		! Read message
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),ICOUNT)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(ICOUNT,IER)
+	   CALL OPEN_BULLFIL_SHARED
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   DO I=BLOCK,BLOCK+LENGTH-1
+	      READ (1'I,IOSTAT=IER) INQUEUE
+              CALL WRITE_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   END DO
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   REC_SAVE(UNIT_INDEX) = 128
+	   LEN_SAVE(UNIT_INDEX) = LENGTH
+           CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   OUT_SAVE(UNIT_INDEX) = OENTRY
+	   CALL WRITE_CHAN(REC_SAVE(UNIT_INDEX),INQUEUE,UNIT_INDEX,IER)
+	   CALL SAVE_LAST_READ_BTIM(UNIT_INDEX)
+	ELSE IF (CMD_TYPE.EQ.10) THEN		! Replacing bulletin
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR
+	   CALL LIB$MOVC3(56,%REF(BUFFER(5:)),%REF(DESCRIP_TEMP))
+	   P = LEN(DESCRIP_TEMP) + 5
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),ICOUNT)
+	   P = 4 + P
+	   CALL READDIR(ICOUNT,IER)
+	   IF (IER.EQ.ICOUNT.OR.DESCRIP_TEMP.NE.DESCRIP) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Cannot find message to replace.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL LIB$MOVC3(56,%REF(BUFFER(P:)),%REF(DESCRIP))
+	   P = LEN(DESCRIP) + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),%REF(MSGTYPE))
+	   P = 4 + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXDATE))
+	   P = LEN(EXDATE) + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXTIME))
+	   P = LEN(EXTIME) + P
+	   ALLOW = (FOLDER_OWNER.EQ.USERNAME).OR.SETPRV_PRIV()
+	   IF ((FOLDER_NUMBER.GT.0.AND.(BTEST(MSGTYPE,0).OR.
+     &		BTEST(MSGTYPE,2)).AND..NOT.BTEST(FOLDER_FLAG,2)).OR.
+     &		(USERNAME.NE.FROM.AND..NOT.ALLOW).OR.
+     &		((MSGTYPE.AND..NOT.8).NE.0.AND..NOT.ALLOW)) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Insufficient privileges to replace message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL READDIR(0,IER)			! Get NBLOCK
+	   CALL OPEN_BULLFIL
+	   NEW_LENGTH = LEN_SAVE(UNIT_INDEX)
+	   LEN_SAVE(UNIT_INDEX) = 0
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   DO I=1,NEW_LENGTH
+	      CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	      WRITE (1'NBLOCK+I) INQUEUE
+	   END DO
+	   CALL CLOSE_BULLFIL			! Finished adding bulletin
+	   IF (NEW_LENGTH.GT.0) THEN
+	      NEMPTY = NEMPTY + LENGTH
+	      LENGTH = NEW_LENGTH
+	      BLOCK = NBLOCK + 1
+	   END IF
+	   CALL WRITEDIR(ICOUNT,IER)
+	   NBLOCK = NBLOCK + NEW_LENGTH
+	   CALL WRITEDIR(0,IER)
+	   CALL UPDATE_DIR_HEADER(BTEST(MSGTYPE,3),BTEST(MSGTYPE,1),
+     &		BTEST(MSGTYPE,2),EXDATE,EXTIME)
+	   IF (BTEST(MSGTYPE,0)) THEN
+	      SYSTEM = IBSET(SYSTEM,0)		! System?
+	   ELSE
+	      SYSTEM = IBCLR(SYSTEM,0)		! General?
+	   END IF
+	   CALL WRITEDIR(ICOUNT,IER)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.11) THEN		! Undeleting
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),BULL_DELETE)
+	   P = 4 + P
+	   CALL LIB$MOVC3(56,%REF(BUFFER(P:)),%REF(DESCRIP_TEMP))
+	   P = LEN(DESCRIP_TEMP) + P
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(BULL_DELETE,IER)
+	   IF (IER.EQ.BULL_DELETE.OR.DESCRIP.NE.DESCRIP_TEMP) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Cannot find message to undelete.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   ELSE IF (USERNAME.NE.FROM.AND.FROM_SAVE(UNIT_INDEX).NE.FROM
+     &	    .AND.FOLDER_OWNER.NE.USERNAME.AND..NOT.SETPRV_PRIV()) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Insufficient privileges to undelete message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXDATE))
+	   P = LEN(EXDATE) + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXTIME))
+	   P = LEN(EXTIME) + P
+	   CALL WRITEDIR(BULL_DELETE,IER)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.12) THEN		! Find newest bulletin
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(0,IER)
+	   CALL GET_NEWEST_MSG(%REF(BUFFER(5:)),BULL_POINT)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(4,%DESCR(BULL_POINT),UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.14) THEN		! Register remote folder
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),FLAG)
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL OPEN_BULLUSER_SHARED
+	   TEMP_USER = ':'//NODENAME(:TRIM(NODENAME))
+	   DO WHILE (REC_LOCK(IER))
+	      READ (4,KEY=TEMP_USER,IOSTAT=IER) 
+     &		TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG
+	   END DO
+	   IF (IER.NE.0) THEN
+	      DO I=1,FLONG
+		 NEW_FLAG (I) = 0
+	      END DO
+	   END IF
+	   IF (FLAG) THEN
+	      CALL SET2(NEW_FLAG,FOLDER_NUMBER)
+	   ELSE
+	      CALL CLR2(NEW_FLAG,FOLDER_NUMBER)
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      REWRITE (4) TEMP_USER,
+     &				LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+	   ELSE
+	      TEMP_USER =  ':'//NODENAME(:TRIM(NODENAME))
+	      WRITE (4) TEMP_USER,
+     &				LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+	   END IF
+	   CALL CLOSE_BULLUSER
+	ELSE IF (CMD_TYPE.EQ.15) THEN		! Broadcast message
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),BLENGTH)
+	   CALL LIB$MOVC3(4,%REF(BUFFER(9:)),START)
+	   IF (BLENGTH.EQ.-1) THEN
+	      IF (SCRATCH(UNIT_INDEX).EQ.0) THEN
+		 CALL LIB$GET_VM(BRDCST_LIMIT,SCRATCH(UNIT_INDEX))
+	      END IF
+	      CALL LIB$MOVC3(ILEN-12,%REF(BUFFER(13:)),
+     &				%VAL(SCRATCH(UNIT_INDEX)+START-1))
+	   ELSE
+	      CALL LIB$MOVC3(BLENGTH,%VAL(SCRATCH(UNIT_INDEX)),
+     &				%REF(BMESSAGE(1:)))
+	      CALL LIB$MOVC3(4,%REF(BUFFER(13:)),ALL)
+	      CALL LIB$MOVC3(4,%REF(BUFFER(17:)),CLUSTER)
+	      CALL LIB$FREE_VM(BRDCST_LIMIT,SCRATCH(UNIT_INDEX))
+	      IF (ILEN.GT.20) THEN
+	         CALL LIB$MOVC3(4,%REF(BUFFER(21:)),FOLDER_NUMBER)
+	         FOLDER = BUFFER(44:)
+		 GO TO 100
+	      ELSE IF (SETPRV_PRIV().OR.OPER_PRIV()) THEN
+	         CALL BROADCAST(ALL,CLUSTER)
+	      END IF
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.16) THEN		! Change folder nodename
+ 	   CALL OPEN_BULLFOLDER_SHARED
+	   IER = 0
+	   DO WHILE (IER.EQ.0)
+	      CALL READ_FOLDER_FILE(IER)
+	      IF ('::'//BUFFER(5:TRIM(BUFFER(:12))).EQ.
+     &		  FOLDER_BBOARD(:TRIM(BUFFER(:12))+2).AND.IER.EQ.0) THEN
+	         FOLDER_BBOARD(3:) = BUFFER(13:TRIM(BUFFER(:20)))
+	         CALL REWRITE_FOLDER_FILE(IER)
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLFOLDER
+	END IF
+
+1000	CALL COPY2(PROCPRIV,BULLCP_PRIV)
+
+	IF (FOLDER_DIRECTORY.NE.FOLDER2_DIRECTORY) THEN
+	   FOLDER_DIRECTORY = FOLDER2_DIRECTORY
+	   CALL ADD_DIRECTORIES
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_REMOTE_USERINFO(UNIT_INDEX)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	DIMENSION SAVE_BTIM(2)
+
+	USERNAME = USER_SAVE(UNIT_INDEX)
+	FOLDER_NUMBER = FOLDER_NUM(UNIT_INDEX)
+
+	IF (USERNAME.EQ.'DECNET'.OR.FOLDER_NUMBER.LT.0) RETURN
+
+	CALL OPEN_USERINFO
+	DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				LAST_SAVE(1,UNIT_INDEX))
+	IF (DIFF.LT.0) THEN
+	   LAST_READ_BTIM(1,FOLDER_NUMBER+1) = LAST_SAVE(1,UNIT_INDEX)
+	   LAST_READ_BTIM(2,FOLDER_NUMBER+1) = LAST_SAVE(2,UNIT_INDEX)
+	END IF
+
+	IF (LAST_SYS_BTIM(1,FOLDER_NUMBER+1).EQ.0.AND.
+     &	    LAST_SYS_BTIM(2,FOLDER_NUMBER+1).EQ.0.AND.
+     &	    LAST_SYS_SAVE(1,UNIT_INDEX).NE.0.AND.
+     &	    LAST_SYS_SAVE(2,UNIT_INDEX).NE.0) THEN
+ 	   DIFF1 = -1
+	ELSE IF (LAST_SYS_SAVE(1,UNIT_INDEX).NE.0.AND.
+     &	    LAST_SYS_SAVE(2,UNIT_INDEX).NE.0) THEN
+	   DIFF1 = COMPARE_BTIM(LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &				LAST_SYS_SAVE(1,UNIT_INDEX))
+	ELSE
+	   DIFF1 = 0
+	END IF
+
+	IF (DIFF1.LT.0) THEN
+	   LAST_SYS_BTIM(1,FOLDER_NUMBER+1) = LAST_SYS_SAVE(1,UNIT_INDEX)
+	   LAST_SYS_BTIM(2,FOLDER_NUMBER+1) = LAST_SYS_SAVE(2,UNIT_INDEX)
+	END IF
+
+	IF (DIFF1.LT.0.OR.DIFF.LT.0) CALL UPDATE_USERINFO
+
+	RETURN
+
+	ENTRY SAVE_LAST_READ_BTIM(UNIT_INDEX)
+
+	CALL SYS_BINTIM(DATE//' '//TIME,SAVE_BTIM)
+
+	DIFF = COMPARE_BTIM(LAST_SAVE(1,UNIT_INDEX),SAVE_BTIM)
+
+	IF (DIFF.GE.0) RETURN
+
+	LAST_SAVE(1,UNIT_INDEX) = SAVE_BTIM(1)
+	LAST_SAVE(2,UNIT_INDEX) = SAVE_BTIM(2)
+
+	RETURN
+
+	ENTRY SAVE_LAST_SYS_BTIM(UNIT_INDEX)
+
+	CALL SYS_BINTIM('-',SAVE_BTIM)			! Get today's date
+
+	LAST_SYS_SAVE(1,UNIT_INDEX) = SAVE_BTIM(1)
+	LAST_SYS_SAVE(2,UNIT_INDEX) = SAVE_BTIM(2)
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE CHECK_BULLETIN_PRIV(USERNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	INCLUDE 'BULLFILES.INC'
+
+	IER = SETPRV_PRIV()
+
+	IF ((PROCPRIV(1).AND.NEEDPRIV(1)).EQ.0.AND.
+     &	    (PROCPRIV(2).AND.NEEDPRIV(2)).EQ.0) THEN
+	   CALL CHECK_ACCESS(BULLUSER_FILE(:TRIM(BULLUSER_FILE)),
+     &		USERNAME,R_ACCESS,W_ACCESS)
+	   IF (R_ACCESS) CALL COPY2(PROCPRIV,NEEDPRIV)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETACC(ACCOUNT)
+C
+C  SUBROUTINE GETACC
+C
+C  FUNCTION:
+C	To get account of present process.
+C  OUTPUTS:
+C	ACCOUNT   -   ACCOUNT owner of present process.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) ACCOUNT		! Limit is 12 characters
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(LEN(ACCOUNT),JPI$_ACCOUNT,%LOC(ACCOUNT))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GETSTS(STS)
+C
+C  SUBROUTINE GETSTS
+C
+C  FUNCTION:
+C	To get status of present process. This tells if its a batch process.
+C  OUTPUTS:
+C	STS   -   Status word of present process.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,JPI$_STS,%LOC(STS))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	RETURN
+	END
+
+
+
+
+
+	INTEGER FUNCTION LNM_MODE_EXEC(FAB,RAB,LUN)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FABDEF)'
+	INCLUDE '($RABDEF)'
+
+	RECORD /FABDEF/ FAB
+	RECORD /RABDEF/ RAB
+
+	FAB.FAB$B_ACMODES = ISHFT(1,FAB$V_LNM_MODE)
+
+	STATUS = SYS$OPEN(FAB)
+	IF (STATUS) STATUS = SYS$CONNECT(RAB)
+
+	LNM_MODE_EXEC = STATUS
+
+	END
+
+
+
+	INTEGER FUNCTION REC_LOCK(IER)
+
+	INCLUDE '($FORIOSDEF)'
+
+	DATA INIT /.TRUE./
+
+	IF (INIT) THEN
+	   REC_LOCK = 1
+	   INIT = .FALSE.
+	ELSE
+	   IF (IER.EQ.FOR$IOS_SPERECLOC) THEN
+	      CALL WAIT_SEC('01')
+	      INIT = INIT + 2
+	      IF (INIT.GT.60) THEN
+		 WRITE (6,'('' Bulletin aborting due to record lock'',
+     &			    '' problem.  Alert system administrator.'')')
+		 CALL EXIT
+	      END IF
+	   ELSE
+	      REC_LOCK = 0
+	      INIT = .TRUE.
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+	INTEGER FUNCTION TRIM(INPUT)
+	CHARACTER*(*) INPUT
+	DO TRIM=LEN(INPUT),1,-1
+	 IF (INPUT(TRIM:TRIM).NE.' '.AND.INPUT(TRIM:TRIM).NE.CHAR(0)) RETURN
+	END DO
+	RETURN
+	END
+
+	SUBROUTINE SYS_GETMSG(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /WINDOW/ WINDOW
+
+	CHARACTER*80 MESSAGE
+
+	WINDOW = 1
+	CALL LIB$SYS_GETMSG(IER,,MESSAGE)
+	WRITE (6,'(A)') MESSAGE
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE HELP(LIBRARY)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) LIBRARY
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	IER = CLI$GET_VALUE('HELP_FOLDER',BULL_PARAMETER,LEN_P)
+	IF (.NOT.IER) BULL_PARAMETER = ' '
+
+	CALL OUTPUT_HELP(BULL_PARAMETER(1:LEN_P),LIBRARY)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NODE_INFO
+C
+C  SUBROUTINE GET_NODE_INFO
+C
+C  FUNCTION: Gets local node name and obtains node names from
+C	command line.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	EXTERNAL CLI$_ABSENT
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+
+	COMMON /TEMP_INPUT/ NODE_TEMP
+	CHARACTER NODE_TEMP*256
+
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	CHARACTER LOCAL_NODE*32,PASSWORD*32,TEMP_USER*12
+
+	NODE_ERROR = .FALSE.
+
+	LOCAL_NODE_FOUND = .FALSE.
+	CALL LIB$SYS_TRNLOG('SYS$NODE',L_NODE,LOCAL_NODE)
+	L_NODE = L_NODE - 2			! Remove '::'
+	IF (LOCAL_NODE(1:1).EQ.'_') THEN
+	   LOCAL_NODE = LOCAL_NODE(2:)
+	   L_NODE = L_NODE - 1
+	END IF
+
+	NODE_NUM = 0				! Initialize number of nodes
+	IF (CLI$PRESENT('NODES')) THEN		! Decnet nodes specified?
+	   DO WHILE (CLI$GET_VALUE('NODES',NODE_TEMP)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified nodes
+	    IER = SYS_TRNLNM(NODE_TEMP,NODE_TEMP)
+	    DO WHILE (TRIM(NODE_TEMP).GT.0)
+	      NODE_NUM = NODE_NUM + 1
+	      COMMA = INDEX(NODE_TEMP,',')
+	      IF (COMMA.GT.0) THEN
+		 NODES(NODE_NUM) = NODE_TEMP(1:COMMA-1)
+		 NODE_TEMP = NODE_TEMP(COMMA+1:)
+	      ELSE
+		 NODES(NODE_NUM) = NODE_TEMP
+		 NODE_TEMP = ' '
+	      END IF
+	      NLEN = TRIM(NODES(NODE_NUM))
+	      I = INDEX(NODES(NODE_NUM),'::')
+	      TEMP_USER = ' '
+	      IF (I.GT.0.AND.NLEN-I.EQ.1) THEN
+		 NLEN = NLEN - 2
+		 NODES(NODE_NUM) = NODES(NODE_NUM)(:NLEN)
+	      ELSE IF (I.GT.0.AND.NLEN-I.GT.1) THEN
+		 TEMP_USER = NODES(NODE_NUM)(I+2:)
+		 NLEN = I - 1
+		 NODES(NODE_NUM) = NODES(NODE_NUM)(:NLEN)
+	         POINT_NODE = NODE_NUM
+	         IER = 1
+	         DO WHILE (IER.NE.0)
+	            WRITE(6,'('' Enter password for node '',2A)')
+     &			NODES(NODE_NUM)(:NLEN),CHAR(10)
+		    CALL GET_INPUT_NOECHO(PASSWORD)
+		    IF (TRIM(PASSWORD).EQ.0) THEN
+		       DO WHILE (NODE_NUM.GT.0)
+		          CLOSE(UNIT=9+NODE_NUM)
+		          NODE_NUM = NODE_NUM - 1
+		       END DO
+		       NODE_ERROR = .TRUE.
+		       RETURN
+	            END IF
+	            OPEN (UNIT=9+NODE_NUM,NAME=NODES(NODE_NUM)(:NLEN)//
+     &		     '"'//TEMP_USER(:TRIM(TEMP_USER))//' '//
+     &		     PASSWORD(:TRIM(PASSWORD))//'"::'//'"TASK=BULLETIN"',
+     &		     ACCESS='SEQUENTIAL',FORM='FORMATTED',
+     &		     CARRIAGECONTROL='NONE',TYPE='NEW',IOSTAT=IER)
+		    IF (IER.NE.0) THEN
+		       WRITE (6,'('' ERROR: Password is invalid.'')')
+		    END IF
+	         END DO
+	      END IF
+	      IF (LOCAL_NODE(:L_NODE).EQ.NODES(NODE_NUM)(:NLEN)) THEN
+	         NODE_NUM = NODE_NUM - 1
+	         LOCAL_NODE_FOUND = .TRUE.
+	      ELSE IF (TRIM(TEMP_USER).EQ.0) THEN
+	         POINT_NODE = NODE_NUM
+	         OPEN (UNIT=9+NODE_NUM,NAME=NODES(NODE_NUM)(:NLEN)//
+     &		  '::"TASK=BULLETIN"',ACCESS='SEQUENTIAL',FORM='FORMATTED',
+     &		  CARRIAGECONTROL='NONE',TYPE='NEW',IOSTAT=IER)
+	         IF (IER.NE.0) THEN
+		    DO WHILE (NODE_NUM.GT.0)
+		       CLOSE(UNIT=9+NODE_NUM)
+		       NODE_NUM = NODE_NUM - 1
+		    END DO
+		    NODE_ERROR = .TRUE.
+		    RETURN
+	         END IF
+	      END IF
+	    END DO
+	   END DO
+	ELSE
+	   LOCAL_NODE_FOUND = .TRUE.
+	END IF
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_FOLDER_FILE(NUM)
+C
+C  SUBROUTINE SET_FOLDER_FILE
+C
+C  FUNCTION: Sets folder file name.  If NUM = 0, set FOLDER_FILE,
+C		if = 1, set FOLDER1_FILE
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	IF (NUM.EQ.0) THEN
+	   CALL SET_FILE(FOLDER,FOLDER_FLAG,FOLDER_NUMBER,FOLDER_FILE)
+	ELSE IF (NUM.EQ.1) THEN
+	   CALL SET_FILE(FOLDER1,FOLDER1_FLAG,FOLDER1_NUMBER,FOLDER1_FILE)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_FILE(FOLDER,FOLDER_FLAG,FOLDER_NUMBER,FOLDER_FILE)
+C
+C  SUBROUTINE SET_FILE
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*(*) FOLDER,FOLDER_FILE
+
+	IF (.NOT.BTEST(FOLDER_FLAG,8)) THEN
+	   FOLDER_FILE =
+     &		FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//FOLDER
+	ELSE
+	   FOLDER_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY)-1)//
+     &		'.]'
+	END IF
+
+	RETURN
+	END
+
+
+
+
+        SUBROUTINE SET_BULLFIL
+
+        IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+        COMMON /BULLFIL/ BULLFIL
+
+	CHARACTER FILDATE*12
+
+	DATA UPDATE/.FALSE./, JUST_NAME/.FALSE./
+
+	UPDATE = .TRUE.
+	JUST_NAME = .TRUE.
+
+	ENTRY SET_BULLFIL_UPDATE
+
+	UPDATE = .NOT.UPDATE
+	JUST_NAME = .TRUE.
+
+	ENTRY SET_BULLFIL_NAME
+
+	JUST_NAME = .NOT.JUST_NAME
+
+	IER = SYS$ASCTIM(,FILDATE,EX_BTIM,) 
+	IF (.NOT.IER.OR.FILDATE.EQ.'17-NOV-1858 ') 
+     &				IER = SYS$ASCTIM(,FILDATE,,)
+	IF (BULLFIL.EQ.1) FILDATE = EXDATE
+	FILDATE = FILDATE(FIRST_ALPHA(FILDATE):)
+
+	M = INDEX(FILDATE,'-')
+	FOLDER1_FILE = FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWS'//
+     &		FILDATE(INDEX(FILDATE,' ')-2:TRIM(FILDATE))//']'//
+     &		FILDATE(:M-1)//FILDATE(M+1:M+3)
+	
+	IF (FOLDER1_FILE.NE.FOLDER_FILE) THEN 
+	   FOLDER_FILE = FOLDER1_FILE
+	   IF (JUST_NAME) THEN
+	      JUST_NAME = .FALSE.
+	      RETURN
+	   END IF
+	   IF (BULLFIL.GT.0) CALL CLOSE_BULLFIL
+	   IF (BULLFIL.EQ.-1) THEN
+	      BULLFIL = 1
+	      CALL OPEN_BULLFIL
+	   ELSE IF (BULLFIL.EQ.-2) THEN
+	      BULLFIL = 2
+	      CALL OPEN_BULLFIL_SHARED
+	   END IF
+	END IF
+
+	JUST_NAME = .FALSE.
+	
+        IF (UPDATE) THEN	
+	   READ (1'1) NBLOCK
+	   REWRITE (1) NBLOCK + LENGTH
+	   UPDATE = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION MINGT0(I,J)
+
+        IMPLICIT INTEGER (A-Z)
+
+	IF (I.LE.0) THEN
+	   MINGT0 = J
+	ELSE IF (J.LE.0) THEN
+	   MINGT0 = I
+	ELSE
+	   MINGT0 = MIN(I,J)
+	END IF	
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bulletin9.for b/decus/vmslt00a/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..0a54525223ec224e0ee55560aabbe06ee2b208e6
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulletin9.for
@@ -0,0 +1,2474 @@
+C
+C  BULLETIN9.FOR, Version 4/8/98
+C  Purpose: Contains subroutines for the bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE DELETE_NODE
+C
+C  SUBROUTINE DELETE_NODE
+C
+C  FUNCTION: Deletes files sent via ADD/NODES at remote hosts.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+    	CHARACTER INLINE*80
+
+	CALL GET_NODE_INFO
+
+ 	IF (NODE_ERROR) GO TO 940
+
+	IF (NODE_NUM.EQ.0.OR.LOCAL_NODE_FOUND) THEN
+	   WRITE (6,'('' ERROR: Cannot specify local node.'')')
+	   GO TO 999
+	END IF
+
+	IER = CLI$GET_VALUE('SUBJECT',DESCRIP)
+
+	DO POINT_NODE=1,NODE_NUM	   	! Write out command to nodes
+	   NLEN = TRIM(NODES(POINT_NODE))	! Length of node name
+	   INLINE = 'DELETE/SUBJECT="'//DESCRIP(:TRIM(DESCRIP))
+	   WRITE (POINT_NODE+9,'(A)',ERR=940) INLINE
+	   READ (POINT_NODE+9,'(A)',ERR=940,END=940) INLINE
+	   IF (INLINE.EQ.'END') THEN
+	      WRITE (6,'('' Message successfully deleted from node '',A)')
+     &				NODES(POINT_NODE)
+	   ELSE
+	      WRITE (6,'('' Error while deleting message to node '',A)')
+     &				NODES(POINT_NODE)
+	      WRITE (6,'(A)') INLINE
+	   END IF
+	END DO
+
+	GO TO 999
+
+940	WRITE (6,1015) NODES(POINT_NODE)
+
+999	DO WHILE (NODE_NUM.GT.0)
+	   CLOSE(UNIT=9+NODE_NUM)
+	   NODE_NUM = NODE_NUM - 1
+	END DO
+
+	RETURN
+
+1015	FORMAT (' ERROR: Unable to reach node ',A)
+
+	END
+
+
+
+
+	SUBROUTINE SET_FOLDER_FLAG(SETTING,FLAG,FLAGNAME)
+C
+C  SUBROUTINE SET_FOLDER_FLAG
+C
+C  FUNCTION: Sets or clears specified flag for folder
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) FLAGNAME
+
+	IF (REMOTE_SET.EQ.3.OR.(REMOTE_SET.EQ.4.AND.FLAG.NE.1)) THEN
+	   WRITE (6,'('' ERROR: Command invalid for folder.'')')
+	ELSE IF ((FLAG.EQ.7.OR.FLAG.EQ.14).AND..NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: Privileges required for this command.'')')
+	ELSE IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+           IF (REMOTE_SET.NE.4) THEN
+	      CALL OPEN_BULLFOLDER		! Open folder file
+	   ELSE
+	      CALL OPEN_BULLNEWS_SHARED
+	   END IF
+
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	   IF (SETTING) THEN
+	      FOLDER_FLAG = IBSET(FOLDER_FLAG,FLAG)
+	   ELSE
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,FLAG)
+	   END IF
+
+	   CALL REWRITE_FOLDER_FILE(IER)
+
+	   CALL CLOSE_BULLFOLDER
+
+	   WRITE (6,'(1X,A,'' has been modified for folder.'')')
+     &		FLAGNAME
+	ELSE
+	   WRITE (6,'(1X,'' You are not authorized to modify '',A)')
+     &		FLAGNAME//'.'
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_FOLDER_EXPIRE_LIMIT(LIMIT)
+C
+C  SUBROUTINE SET_FOLDER_EXPIRE_LIMIT
+C
+C  FUNCTION: Sets folder expiration limit.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   WRITE (6,'('' ERROR: Command invalid for folder. '')')
+	ELSE IF (LIMIT.LT.0) THEN
+	   WRITE (6,'('' ERROR: Invalid expiration length specified.'')')
+	ELSE IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+           IF (REMOTE_SET.NE.4) THEN
+	      CALL OPEN_BULLFOLDER		! Open folder file
+	   ELSE
+	      CALL OPEN_BULLNEWS_SHARED
+	   END IF
+
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	   F_EXPIRE_LIMIT = LIMIT
+
+	   CALL REWRITE_FOLDER_FILE(IER)
+
+	   CALL CLOSE_BULLFOLDER
+	   WRITE (6,'('' Folder expiration date modified.'')')
+	ELSE
+	   WRITE (6,'('' You are not allowed to modify folder.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE MERGE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(DIR_RECORD_LENGTH) BULLDIR_ENTRY_SAVE
+
+	ENTRY INITIALIZE_MERGE(IER1)
+
+	DO WHILE (FILE_LOCK(IER1,IER2))
+	   OPEN (UNIT=24,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &		//'.TMPDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &		RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &		ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &		KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	END DO
+
+	IF (IER1.NE.0) RETURN
+
+	NBULL = 0
+
+	WRITE(24,IOSTAT=IER1) BULLDIR_HEADER
+	CALL CONVERT_HEADER_FROMBIN
+
+	TO_POINTER = 1
+
+	RETURN
+
+	ENTRY ADD_MERGE_TO(IER1)
+ 
+	IER1 = 0
+
+	DO WHILE (IER1.EQ.0)
+
+	   BULLDIR_ENTRY_SAVE = BULLDIR_ENTRY
+
+	   CALL READDIR(TO_POINTER,IER)
+
+	   DIFF = COMPARE_BTIM(%REF(BULLDIR_ENTRY_SAVE),MSG_BTIM)
+	   IF (DIFF.LT.0.OR.TO_POINTER+1.NE.IER) THEN
+	      BULLDIR_ENTRY = BULLDIR_ENTRY_SAVE
+	      CALL CONVERT_ENTRY_FROMBIN
+	      RETURN
+	   END IF
+
+	   NBULL = NBULL + 1
+	   MSG_NUM = NBULL
+
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   WRITE(24,IOSTAT=IER1) BULLDIR_ENTRY
+
+	   NEWEST_DATE = DATE
+	   NEWEST_TIME = TIME
+
+	   TO_POINTER = TO_POINTER + 1
+
+	   BULLDIR_ENTRY = BULLDIR_ENTRY_SAVE
+	END DO
+
+	CLOSE (UNIT=24)
+
+	RETURN
+
+	ENTRY ADD_MERGE_FROM(IER1)
+
+	NEWEST_DATE = DATE
+	NEWEST_TIME = TIME
+
+	DIFF = COMPARE_DATE(NEWEST_EXDATE,EXDATE)
+	IF (DIFF.GT.0) THEN
+	   NEWEST_EXDATE = EXDATE
+	   NEWEST_EXTIME = EXTIME
+	ELSE IF (DIFF.EQ.0) THEN
+	   DIFF = COMPARE_TIME(NEWEST_EXTIME,EXTIME)
+	   IF (DIFF.GT.0) NEWEST_EXTIME = EXTIME
+	END IF
+
+	IF ((SYSTEM.AND.4).EQ.4) THEN
+	   SHUTDOWN = SHUTDOWN + 1
+	   SHUTDOWN_DATE = DATE
+	   SHUTDOWN_TIME = TIME
+	END IF
+
+	BLOCK = NBLOCK - LENGTH
+
+	NBULL = NBULL + 1
+	MSG_NUM = NBULL
+
+	CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	WRITE(24,IOSTAT=IER1) BULLDIR_ENTRY
+
+	RETURN
+
+	ENTRY ADD_MERGE_REST(IER1)
+
+	CALL UPDATE_LOGIN(.TRUE.)
+
+	DO WHILE (IER1.EQ.0)
+
+	   CALL READDIR(TO_POINTER,IER)
+	   IF (TO_POINTER+1.NE.IER) THEN
+	      READ (24,KEYID=0,KEY=0,IOSTAT=IER1)
+	      CALL CONVERT_HEADER_TOBIN
+	      REWRITE(24,IOSTAT=IER1) BULLDIR_HEADER
+	      IF (IER1.EQ.0) THEN
+	         CLOSE (UNIT=24,DISPOSE='KEEP')
+	         CALL LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &		  '.TMPDIR',FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLDIR')
+	      ELSE
+		 CLOSE (UNIT=24)
+	      END IF
+	      RETURN
+	   END IF
+
+	   NBULL = NBULL + 1
+	   MSG_NUM = NBULL
+
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   WRITE(24,IOSTAT=IER1) BULLDIR_ENTRY
+
+	   NEWEST_DATE = DATE
+	   NEWEST_TIME = TIME
+
+	   TO_POINTER = TO_POINTER + 1
+	END DO
+
+	CLOSE (UNIT=24)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_NOKEYPAD
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+	INCLUDE '($SMGDEF)'
+
+	KEYPAD_MODE = 0
+
+	TERM = SMG$M_KEY_TERMINATE
+
+	IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,0)
+
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF2',,TERM,'SET KEYPAD',)
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE SET_KEYPAD
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+        COMMON /KEYLOAD/ LOAD_KEY
+
+	INCLUDE '($SMGDEF)'
+
+	KEYPAD_MODE = 1
+
+	TERM = SMG$M_KEY_TERMINATE
+
+	IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,1)
+
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF1',,,,'GOLD')
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF2',,TERM,'HELP',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF2','GOLD',TERM,'SET NOKEYPAD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF3',,,'EXTRACT ',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF3','GOLD',,'FILE ',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF4',,TERM,'SHOW KEYPAD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF4','GOLD',TERM,
+     &		'SHOW KEYPAD/PRINT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP0',,TERM,
+     &		'SHOW FOLDER/FULL',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP0','GOLD',TERM,'SHOW FLAGS',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP1',,TERM,'BACK',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP1','GOLD',TERM,'NEXT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP2',,TERM,'PRINT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP2','GOLD',TERM,'PRINT/NONOTIFY',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP3',,TERM,'DIR',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP3','GOLD',TERM,'DIR/FOLDER',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP4',,TERM,'CURRENT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP4','GOLD',TERM,'CURRENT/EDIT ',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP5',,TERM,'RESPOND',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP5','GOLD',TERM,'RESP/EDIT/EXT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP6',,TERM,'LAST',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP7',,TERM,'ADD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP7','GOLD',TERM,'ADD/EDIT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP8',,TERM,'REPLY',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP8','GOLD',TERM,'REPL/EDIT/EXT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP9',,TERM,'MAIL',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP9','GOLD',TERM,'MAIL/NOHEAD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'MINUS',,TERM,'READ/NEW',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'MINUS','GOLD',TERM,'SHOW NEW',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'COMMA',,TERM,'DIR/NEW',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'COMMA','GOLD',TERM,'INDEX',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PERIOD',,TERM,'DELETE',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PERIOD','GOLD',TERM,'UNDELETE',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'ENTER','GOLD',,'SELECT ',)
+
+        LOAD_KEY = SMG$LOAD_KEY_DEFS(KEY_TABLE_ID,'BULL_INIT',
+     &				'SYS$LOGIN:BULL.INI',1)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SHOW_KEYPAD(LIBRARY)
+
+	IMPLICIT INTEGER (A-Z)
+	EXTERNAL LIB$PUT_OUTPUT,PRINT_OUTPUT
+	CHARACTER*(*) LIBRARY
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+        COMMON /KEYLOAD/ LOAD_KEY
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	INCLUDE '($HLPDEF)'
+
+	CHARACTER KEY*10,EQU*50,ST*20,IFS*20
+
+	OUT = 6
+
+	IF (CLI$PRESENT('PRINT')) THEN
+	   OPEN (UNIT=8,STATUS='NEW',FILE='SYS$LOGIN:KEYPAD.DAT',
+     &			IOSTAT=IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR WHILE OPENING FILE TO PRINTER.'')')
+	      RETURN
+	   END IF
+	   OUT = 8
+	END IF      
+
+	IF (CLI$GET_VALUE('SHOW_KEY',KEY,I)) THEN
+	   DO WHILE (CLI$GET_VALUE('STATE',IFS,J))
+              IER = SMG$GET_KEY_DEF(
+     &			KEY_TABLE_ID,KEY(:I),IFS(:J),ATT,EQU,ST)
+              WRITE (OUT,'(3X,A,$)') KEY(:TRIM(KEY))//' = '//'"'//
+     &                                  EQU(:TRIM(EQU))//'"'
+	      IF (TRIM(ST).GT.0) THEN
+	         WRITE (OUT,'(A,$)') '+ '//'state='//ST(:TRIM(ST))
+	      END IF
+              IF (TRIM(IFS).GT.0.AND.IFS.NE.'DEFAULT') THEN
+                 WRITE (OUT,'(A,$)') '+ '//'ifstate='//IFS(:TRIM(IFS))
+              END IF
+	      WRITE (OUT,'(A)') '+'
+	   END DO
+	   RETURN
+ 	ELSE IF (LOAD_KEY) THEN
+	   C = 0
+	   IER = 1
+	   WRITE (OUT,'(1X,A)') 'Keypad definitions:'
+	   L = 1
+	   DO WHILE (IER)
+	      IER = SMG$LIST_KEY_DEFS(KEY_TABLE_ID,C,KEY,IFS,ATT,EQU,ST)
+	      IF (IER) THEN
+		 WRITE (OUT,'(3X,A,$)') KEY(:TRIM(KEY))//' = '//'"'//
+     &					EQU(:TRIM(EQU))//'"'
+	         IF (TRIM(ST).GT.0) THEN
+		    WRITE (OUT,'(A,$)') '+ '//'state='//ST(:TRIM(ST))
+		 END IF
+                 IF (TRIM(IFS).GT.0.AND.IFS.NE.'DEFAULT') THEN
+                    WRITE (OUT,'(A,$)') '+ '//'ifstate='
+     &						//IFS(:TRIM(IFS))
+                 END IF
+		 WRITE (OUT,'(A)') '+'
+ 		 L = L + 1
+                 IF (PAGING.AND.L.EQ.PAGE_LENGTH-1.AND.OUT.EQ.6) THEN
+                    L = 0                        ! Reinitialize screen counter
+	            CALL LIB$PUT_OUTPUT(' ')
+		    CALL GET_INPUT_NOECHO_PROMPT(
+     &				KEY(:1),'Press key to continue ... ')
+             	    IER = LIB$ERASE_PAGE(1,1)         ! Erase display
+		 END IF
+	      END IF
+	   END DO
+           IF (OUT.EQ.8) CLOSE (UNIT=8,DISP='PRINT/DELETE')
+	   RETURN
+	END IF
+
+	IF (OUT.EQ.8) THEN
+	   CALL LBR$OUTPUT_HELP(PRINT_OUTPUT,,'KEYPAD'
+     &		,LIBRARY,HLP$M_HELP)
+	   CLOSE (UNIT=8,DISP='PRINT/DELETE')
+	ELSE
+	   CALL LBR$OUTPUT_HELP(LIB$PUT_OUTPUT,,'KEYPAD'
+     &		,LIBRARY,HLP$M_HELP)
+	END IF
+
+	RETURN
+	END
+
+	INTEGER FUNCTION PRINT_OUTPUT(INPUT)
+	IMPLICIT INTEGER (A-Z)
+	CHARACTER*(*) INPUT
+	WRITE (8,'(1X,A)',IOSTAT=IER) INPUT(:TRIM(INPUT))
+	IF (IER.EQ.0) PRINT_OUTPUT = 1
+	RETURN
+	END
+
+
+
+	SUBROUTINE OUTPUT_HELP(PARAMETER,LIBRARY)
+C
+C  SUBROUTINE OUTPUT_HELP
+C
+C  FUNCTION:
+C	To create interactive help session.  Prompting is enabled.
+C  INPUTS:
+C	PARAMETER - Character string. Optional input parameter
+C		    containing a list of help keys.
+C	LIBRARY   - Character string. Name of help library.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($LBRDEF)'
+
+	COMMON /HELP/ HELP_PAGE,HELP_INPUT,HELP_INPUT_LEN
+	COMMON /HELP/ NEED_ERASE,KEYBOARD_ID,KEY_TABLE_ID,OTHERINFO
+	CHARACTER*80 HELP_INPUT
+
+	COMMON /LEVELS/ KEY,KEYL,NKEY,OLD_NKEY,EXACT
+	CHARACTER*20 KEY(10)
+	DIMENSION KEYL(10)
+
+	EXTERNAL PUT_OUTPUT
+
+	CHARACTER*(*) LIBRARY,PARAMETER
+
+	CHARACTER*80 PROMPT
+
+	DATA KEYBOARD_ID/0/
+
+	IF (KEYBOARD_ID.EQ.0) THEN
+	   IER = SMG$CREATE_VIRTUAL_KEYBOARD(KEYBOARD_ID,,,,20)
+	   IER = SMG$CREATE_KEY_TABLE(KEY_TABLE_ID)
+	END IF
+
+	CALL STR$TRIM(HELP_INPUT,PARAMETER,HELP_INPUT_LEN)	! Trim input
+
+	CALL LBR$INI_CONTROL(LINDEX,LBR$C_READ)		! Init library read
+	CALL LBR$OPEN(LINDEX,LIBRARY)			! Specify library name
+
+	DO I=1,10					! Initialize key lengths
+	   KEYL(I) = 0
+	END DO
+
+	NKEY = 0					! Number of help keys
+
+	DO WHILE (NKEY.GE.0)	! Do until CTRL-Z entered or no more keys
+
+	   HELP_PAGE = 0				! Init line counter
+	   NEED_ERASE = .TRUE.				! Need to erase screen
+
+	   OLD_NKEY = NKEY				! Save old key count
+	   EXACT = .TRUE.				! Exact key match
+
+	   DO WHILE (NKEY.LT.10.AND.HELP_INPUT_LEN.GT.0.AND.
+     &					   HELP_INPUT(:1).NE.'?')
+							! Break input into keys
+	      NKEY = NKEY + 1				! Increment key counter
+
+	      DO WHILE (HELP_INPUT(1:1).EQ.' '.AND.HELP_INPUT_LEN.GT.0)
+		 HELP_INPUT = HELP_INPUT(2:HELP_INPUT_LEN)	! Strip spaces
+		 HELP_INPUT_LEN = HELP_INPUT_LEN - 1	! at start of input
+	      END DO
+
+	      NEXT_KEY = 2
+
+	      DO WHILE (NEXT_KEY.LE.HELP_INPUT_LEN		! Search for
+     &		  .AND.HELP_INPUT(NEXT_KEY:NEXT_KEY).NE.' '	! space or
+     &		  .AND.HELP_INPUT(NEXT_KEY:NEXT_KEY).NE.'/')	! backslash
+		 NEXT_KEY = NEXT_KEY + 1	! indicating start of next key
+	      END DO
+
+	      IF (NEXT_KEY.GT.HELP_INPUT_LEN) THEN	! Found the last key
+		 KEY(NKEY) = HELP_INPUT(:HELP_INPUT_LEN)	! Key string
+		 KEYL(NKEY) = HELP_INPUT_LEN			! Key length
+		 HELP_INPUT_LEN = 0
+	      ELSE					! Found the next key
+		 KEY(NKEY) = HELP_INPUT(:NEXT_KEY-1)
+		 HELP_INPUT = HELP_INPUT(NEXT_KEY:HELP_INPUT_LEN)
+		 KEYL(NKEY) = NEXT_KEY - 1
+		 HELP_INPUT_LEN = HELP_INPUT_LEN - NEXT_KEY + 1
+	      END IF
+	   END DO
+	   HELP_INPUT_LEN = 0
+	   IER = LBR$GET_HELP(LINDEX,,PUT_OUTPUT,,	! Display help
+     &		   KEY(1)(:KEYL(1)),KEY(2)(:KEYL(2)),
+     &		   KEY(3)(:KEYL(3)),KEY(4)(:KEYL(4)),KEY(5)(:KEYL(5)),
+     &		   KEY(6)(:KEYL(6)),KEY(7)(:KEYL(7)),KEY(8)(:KEYL(8)),
+     &		   KEY(9)(:KEYL(9)),KEY(10)(:KEYL(10)))
+
+	   IF (IER.EQ.0.AND.HELP_INPUT_LEN.GT.0) IER = 1
+		! IER = 0 special case means input given to full screen prompt
+
+	   IF (KEY(NKEY).EQ.'*'.OR..NOT.EXACT) THEN	! If not exact match
+	      DO I=OLD_NKEY+1,NKEY			! then don't update
+		 KEYL(I) = 0				! new keys
+	      END DO
+	      NKEY = OLD_NKEY
+	   END IF
+
+	   IF (IER.AND.NKEY.GT.0.AND.OTHERINFO.EQ.0) THEN ! No subtopics?
+	      KEYL(NKEY) = 0				! Back up one key level
+	      NKEY = NKEY - 1
+	   END IF
+
+	   DO WHILE (HELP_INPUT_LEN.EQ.0.AND.IER.AND.NKEY.GE.0)
+	      IF (NKEY.EQ.0) THEN	! If top level, prompt for topic
+	         IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		   HELP_INPUT,'Topic? ',HELP_INPUT_LEN)
+	      ELSE			! If not top level, prompt for subtopic
+		 LPROMPT = 0		! Create subtopic prompt line
+		 DO I=1,NKEY		! Put spaces in between keys
+		    PROMPT = PROMPT(:LPROMPT)//KEY(I)(:KEYL(I))//' '
+		    LPROMPT = LPROMPT + KEYL(I) + 1
+		 END DO
+		 PROMPT = PROMPT(:LPROMPT)//'Subtopic? '
+		 LPROMPT = LPROMPT + 10
+	         IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		   HELP_INPUT,PROMPT(:LPROMPT),HELP_INPUT_LEN)
+	      END IF
+	      CALL STR$TRIM(HELP_INPUT,HELP_INPUT,HELP_INPUT_LEN)
+	      IF (IER.AND.HELP_INPUT_LEN.EQ.0) THEN	! If RETURN entered
+		 KEYL(NKEY) = 0				! Back up one key level
+		 NKEY = NKEY - 1
+	      END IF
+	   END DO
+
+	   IF (.NOT.IER.OR.NKEY.LT.0) THEN	! If CTRL-Z above top level,
+	      CALL LIB$PUT_OUTPUT(' ')		! Skip line
+	      CALL LBR$CLOSE(LINDEX)		! then close library,
+	      RETURN				! and end help session.
+	   END IF
+
+	END DO
+
+	END
+
+
+
+	INTEGER FUNCTION PUT_OUTPUT(INPUT,INFO,DATA,LEVEL)
+C
+C  FUNCTION PUT_OUTPUT
+C
+C  FUNCTION:
+C	Output routine for input from LBR$GET_HELP.  Displays
+C	help text on terminal with full screen prompting.
+C  INPUTS:
+C	INPUT - Character string.  Line of input text.
+C	INFO  - Longword.  Contains help flag bits.
+C	DATA  - Longword.  Not presently used.
+C	LEVEL - Longword.  Contains current key level.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($HLPDEF)'
+
+	COMMON /LEVELS/ KEY,KEYL,NKEY,OLD_NKEY,EXACT
+	CHARACTER*20 KEY(10)
+	DIMENSION KEYL(10)
+
+	COMMON /HELP/ HELP_PAGE,HELP_INPUT,HELP_INPUT_LEN
+	COMMON /HELP/ NEED_ERASE,KEYBOARD_ID,KEY_TABLE_ID,OTHERINFO
+	CHARACTER*80 HELP_INPUT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	CHARACTER INPUT*(*)
+
+	CHARACTER SPACES*20
+	DATA SPACES /' '/
+
+	OTHERINFO = INFO.AND.HLP$M_OTHERINFO
+
+	IF ((INFO.AND.HLP$M_NOHLPTXT).NE.0) THEN	! Key cannot be found
+	   NEED_ERASE = .FALSE.				! Don't erase screen
+	   IF (HELP_PAGE.EQ.0) THEN		! If first line of help text
+	      DO I=OLD_NKEY+1,NKEY		! remove any new keys that
+		 KEYL(I) = 0			! were inputted, as they are
+	      END DO				! not valid, as no match
+	      NKEY = OLD_NKEY			! could be found.
+	   END IF
+	ELSE IF ((INFO.AND.HLP$M_KEYNAMLIN).NE.0.AND.NKEY.GT.0.AND.
+     &		 LEVEL.GT.OLD_NKEY.AND.KEY(NKEY)(:KEYL(NKEY)).NE.'*'.AND.
+     &		 %LOC(INPUT).NE.0) THEN		! If text contains key names
+			! Update if not wildcard search and they are new keys
+	   IF (KEYL(LEVEL).GT.0) THEN		! If key already updated
+	      EXACT = .FALSE.		! Must be more than one match possible
+	   END IF			! so indicate not exact match.
+	   START_KEY = 1		! String preceeding spaces.
+	   DO WHILE (INPUT(START_KEY:START_KEY).EQ.' ')
+	      START_KEY = START_KEY + 1
+	   END DO
+	   KEY(LEVEL) = INPUT(START_KEY:)			! Store new key
+	   CALL STR$TRIM(KEY(LEVEL),KEY(LEVEL),KEYL(LEVEL))	! & key length
+	ELSE IF (HELP_PAGE.EQ.0) THEN		! If first line of text,
+	   DO I=OLD_NKEY+1,NKEY			! remove any new keys that
+	      KEYL(I) = 0			! were just inputted, allowing
+	   END DO				! this routine to fill them.
+	END IF
+
+	IF (NEED_ERASE) THEN			! Need to erase screen?
+	   IER = LIB$ERASE_PAGE(1,1)		! i.e. start of new topic.
+	   NEED_ERASE = .FALSE.
+	END IF
+
+	HELP_PAGE = HELP_PAGE + 1		! Increment screen counter
+	IF (PAGING.AND.HELP_PAGE.GT.PAGE_LENGTH-2) THEN		! End of page?
+	   HELP_PAGE = 0			! Reinitialize screen counter
+	   CALL LIB$PUT_OUTPUT(' ')	! Skip line and prompt for next screen
+	   IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		HELP_INPUT,'Press RETURN to continue ... ',HELP_INPUT_LEN)
+	   CALL STR$TRIM(HELP_INPUT,HELP_INPUT,HELP_INPUT_LEN)	! Trim input
+	   IF (.NOT.IER.OR.HELP_INPUT_LEN.GT.0) THEN	! CTRL-Z or Text input?
+	      EXACT = .TRUE.	! If more than one match was found and being
+				! displayed, text input specifies that the
+				! current displayed match is desired.
+	      PUT_OUTPUT = 0	! Stop any more of current help display.
+	   ELSE					! Else if RETURN entered
+	      IER = LIB$ERASE_PAGE(1,1)		! Erase display
+	      NSPACES = LEVEL*2		! Number of spaces to indent output
+	      IF ((INFO.AND.HLP$M_KEYNAMLIN).NE.0) NSPACES = NSPACES - 2
+		! Key name lines are indented 2 less than help description.
+	      IF (NSPACES.GT.0) THEN	! Add spaces if present to output
+		 PUT_OUTPUT =  LIB$PUT_OUTPUT(SPACES(:NSPACES)//INPUT)
+	      ELSE			! Else just output text.
+		 PUT_OUTPUT =  LIB$PUT_OUTPUT(INPUT)
+	      END IF
+	      HELP_PAGE = 1		! Increment page counter.
+	   END IF
+	ELSE				! Else if not end of page
+	   NSPACES = LEVEL*2		! Just output text line
+	   IF ((INFO.AND.HLP$M_KEYNAMLIN).NE.0) NSPACES = NSPACES - 2
+	   IF (NSPACES.GT.0) THEN
+	      PUT_OUTPUT = LIB$PUT_OUTPUT(SPACES(:NSPACES)//INPUT)
+	   ELSE
+	      PUT_OUTPUT = LIB$PUT_OUTPUT(INPUT)
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOW_VERSION
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER VERSION*12,DATE*24
+
+	INTEGER BTIM(2)
+
+	CALL READ_HEADER(VERSION,DATE)
+
+	WRITE (6,'(A)') ' BULLETIN Version '//VERSION(:TRIM(VERSION))
+
+	WRITE (6,'(A)') ' Linked on '//DATE(:TRIM(DATE))
+
+	RETURN
+
+	ENTRY SHOW_NEW_VERSION
+
+	CALL READ_HEADER(VERSION,DATE)
+
+	IER = SYS$BINTIM(DATE(:TRIM(DATE)),BTIM)
+	IF (.NOT.IER) RETURN
+
+C	IF (COMPARE_BTIM(READ_BTIM,BTIM).LT.0) THEN
+C	   WRITE (6,'(A)') ' A new BULLETIN executable has been '//
+C     &			   'installed since your last use.'
+C	   WRITE (6,'(A)') 
+C     &		' Type HELP NEW_FEATURES for help on any new features.'
+C	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FULL_DIR
+C
+C	Add INDEX command to BULLETIN, display directories of ALL
+C	folders.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+	INCLUDE 'BULLFILES.INC'
+	INCLUDE 'BULLFOLDER.INC'
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG
+
+        COMMON /NEW_DIR/ NEW
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	DATA FOLDER_Q1/0/
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+
+	CHARACTER NEWS_ACCESS*132,DATETIME*20
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	IF (NUM_FOLDERS.GT.0.AND..NOT.CLI$PRESENT('RESTART')
+     &		.AND.INDEX_COUNT.EQ.1) THEN
+	   INDEX_COUNT = 2
+	   DIR_COUNT = 0
+	END IF
+
+	IF (INDEX_COUNT.EQ.1) THEN
+	  CALL INIT_QUEUE(FOLDER_Q1,FOLDER1_COM)
+
+	  FOLDER_Q = FOLDER_Q1
+
+	  SET = CLI$PRESENT('SET')
+	  NEW = CLI$PRESENT('NEW')
+	  INEW = NEW
+
+	  IREAD_TAG = IBSET(0,1) + IBSET(0,2)
+	  IF (CLI$PRESENT('MARKED')) THEN
+	     IREAD_TAG = 1 + IBSET(0,1)
+	  ELSE IF (CLI$PRESENT('SEEN')) THEN
+	     IREAD_TAG = 1 + IBSET(0,2)
+	  ELSE IF (CLI$PRESENT('UNMARKED').OR.CLI$PRESENT
+     &		   ('MARKED').EQ.%LOC(CLI$_NEGATED)) THEN
+	     IREAD_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+	  ELSE IF (CLI$PRESENT('UNSEEN').OR.CLI$PRESENT
+     &		   ('SEEN').EQ.%LOC(CLI$_NEGATED)) THEN
+	     IREAD_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+ 	  END IF
+
+	  NEW = NEW.AND..NOT.IREAD_TAG
+
+	  SUBSCRIBE = CLI$PRESENT('SUBSCRIBE')
+	  IF (SUBSCRIBE) THEN
+	     CALL NEWS_GET_SUBSCRIBE(0,F1_COUNT)
+	     SUBNUM = 1
+	     CALL OPEN_BULLNEWS_SHARED
+	  ELSE
+	     CALL OPEN_BULLFOLDER_SHARED
+	  END IF
+
+	  NUM_FOLDERS = 0
+	  IER = 0
+	  DO WHILE (IER.EQ.0)			! Copy all bulletins from file
+	    IF (SUBSCRIBE) THEN
+	       IER = 1
+	       DO WHILE (SUBNUM.NE.0.AND.IER.NE.0)
+	          CALL NEWS_GET_SUBSCRIBE(SUBNUM,MSGNUM)
+		  IF (SUBNUM.NE.0) THEN
+	             CALL READ_FOLDER_FILE_KEYNUM_TEMP(SUBNUM,IER)
+		     IF (IER.NE.0) THEN
+			SUBNUM = -1
+		     ELSE IF (NEW.AND.(MSGNUM.GE.F1_NBULL.OR.F1_NBULL
+     &			  .EQ.0.OR.F1_START.GT.F1_NBULL)) THEN
+		        IER = 1
+	             END IF
+		  END IF
+	       END DO
+	       IF (SUBNUM.EQ.0) IER = 1
+	    ELSE
+	       FOUND = .FALSE.
+	       DO WHILE (.NOT.FOUND.AND.IER.EQ.0)
+	          CALL READ_FOLDER_FILE_TEMP(IER)
+	          IF (IER.EQ.0) THEN
+		     IF (.NOT.SET.OR.TEST2(SET_FLAG,FOLDER1_NUMBER)
+     &			.OR.TEST2(BRIEF_FLAG,FOLDER1_NUMBER)) THEN
+			FOUND = .NOT.NEW.OR.COMPARE_BTIM(LAST_READ_BTIM
+     &			   (1,FOLDER1_NUMBER+1),F1_NEWEST_BTIM).LT.0
+                     END IF
+	          END IF
+	       END DO
+	    END IF
+	    IF (IER.EQ.0) THEN
+	      IF (BTEST(FOLDER1_FLAG,0).AND..NOT.SETPRV_PRIV()) THEN
+		 FOLDER1_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &					//FOLDER1
+	         IF (SUBSCRIBE) THEN
+	            CALL CHECK_ACCESS
+     &		     (NEWS_ACCESS(FOLDER_DESCRIP),
+     &		      USERNAME,READ_ACCESS,-1)
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		      USERNAME,READ_ACCESS,-1)
+	         END IF
+	      ELSE
+		 READ_ACCESS = 1
+	      END IF
+	      IF (READ_ACCESS) THEN
+	         NUM_FOLDERS = NUM_FOLDERS + 1
+	         CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER1_COM)
+	      END IF
+	    END IF
+	  END DO
+
+	  CALL CLOSE_BULLFOLDER			! We don't need file anymore
+
+	  FOLDER_Q = FOLDER_Q1			! Init queue pointer to header
+	  IF (NEW) THEN
+	     WRITE (6,1010)
+	  ELSE
+	     WRITE (6,1000)
+	  END IF
+	  IF (.NOT.SUBSCRIBE) THEN
+	     WRITE (6,'(1X,''Folder'',22X,''Last message'',7X,''Messages'',
+     &		2X,''Owner'',/,1X,80(''-''))')
+	  ELSE
+	     WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,1X,
+     &		''First        Last   Last Read'',/,1X,<PAGE_WIDTH>(''-''))')
+	  END IF
+          NUM_FOLDER = 0
+	  IF (SUBSCRIBE) FLEN = MIN(81,PAGE_WIDTH-80+42)
+	  DO I = 1,NUM_FOLDERS
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER1_COM)
+	   IF (SUBSCRIBE) THEN
+	      J = INDEX(FOLDER1_DESCRIP,' ')
+	      IF (J.GT.0.AND.FOLDER1_DESCRIP(J+1:J+1).NE.'=') THEN
+                 FOLDER1_DESCRIP = FOLDER1_DESCRIP(:J-1)
+              END IF
+	      IF (F1_START.LE.F1_NBULL) THEN
+                 NEWS_FOLDER1_NUMBER = FOLDER1_NUMBER
+		 CALL NEWS_GET_NEWEST_MESSAGE1(NEWS_NEW)
+	         WRITE (6,1015) '*'//FOLDER1_DESCRIP(:FLEN-1),
+     &					F1_START,F1_NBULL,NEWS_NEW-1
+              ELSE
+	         WRITE (6,1015) ' '//FOLDER1_DESCRIP(:FLEN-1),0,0,0
+	      END IF
+	   ELSE
+	      IF (F1_NBULL.GT.0) THEN
+	         CALL SYS$ASCTIM(,DATETIME,F1_NEWEST_BTIM,)
+	      ELSE
+	         DATETIME = '      NONE'
+	      END IF
+	      WRITE (6,1030) FOLDER1,DATETIME(:17),F1_NBULL,
+     &							FOLDER1_OWNER
+	   END IF
+	   NUM_FOLDER = NUM_FOLDER + 1
+	   IF (I.NE.NUM_FOLDERS.AND.PAGING.AND.((NUM_FOLDER+6.EQ.PAGE_LENGTH
+     &		.AND.I.EQ.NUM_FOLDER).OR.(NUM_FOLDER+2.EQ.PAGE_LENGTH.AND.
+     &		I.NE.NUM_FOLDER))) THEN
+	      NUM_FOLDER = 0
+	      WRITE(6,1080)	! Ask for input to proceed to next page
+	      CALL GET_INPUT_NOECHO_PROMPT(DATETIME(:1),
+     &			'HIT any key for next page....')
+	   END IF
+	  END DO
+	  IF (NUM_FOLDERS.EQ.0) THEN
+	     WRITE (6,1050)
+	     INDEX_COUNT = 0
+	     RETURN
+	  END IF
+	  WRITE (6,1060)
+	  FOLDER_Q = FOLDER_Q1			! Init queue pointer to header
+	  INDEX_COUNT = 2
+	  DIR_COUNT = 0
+	  RETURN
+	ELSE IF (INDEX_COUNT.EQ.2) THEN
+	 READ_TAG = IREAD_TAG
+	 IF (DIR_COUNT.LE.0) THEN
+	  F1_NBULL = 0
+	  DIR_COUNT = 0
+	  DO WHILE (NUM_FOLDERS.GT.0.AND.F1_NBULL.EQ.0)
+	     NUM_FOLDERS = NUM_FOLDERS - 1
+	     CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER1_COM)
+	     IF (F1_NBULL.GT.0) THEN
+	      FOLDER_NUMBER = -1
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (.NOT.IER) F1_NBULL = 0
+	     END IF
+	  END DO
+
+	  IF (F1_NBULL.EQ.0) THEN
+	     WRITE (6,1050)
+	     INDEX_COUNT = 0
+	     RETURN
+	  END IF
+	 END IF
+     
+	 IF (READ_TAG) THEN
+	    CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,BULL_POINT)
+	 ELSE IF (INEW) THEN
+	    NEW = INEW
+            IF (REMOTE_SET.GE.3) THEN
+	       CALL NEWS_GET_NEWEST_MESSAGE(IER)
+	       IF (IER.GT.0.AND.IER.LE.F_NBULL) BULL_POINT = IER - 1	
+	    ELSE
+	       CALL FIND_NEWEST_BULL
+	    END IF
+	 END IF
+
+	 IF (INCMD(:4).NE.'INDE') THEN 
+	    IER = CLI$DCL_PARSE('INDEX',BULLETIN_SUBCOMMANDS)
+	 END IF
+
+	 CALL DIRECTORY(DIR_COUNT)
+	 IF (DIR_COUNT.GT.0) RETURN
+
+	 IF (NUM_FOLDERS.GT.0) THEN
+	    WRITE (6,1040)
+	 ELSE
+	    INDEX_COUNT = 0
+	 END IF
+	END IF
+
+	RETURN
+
+1000	FORMAT (' The following folders are present'/)
+1010	FORMAT (' The following folders with new messages are present'/)
+1015    FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-36-1>X,2X,I10,2X,I10,2X,I10)
+1030	FORMAT(1X,A26,2X,A17,2X,I8,2X,A12)
+1035	FORMAT (1X,A,1X,I6)
+1040	FORMAT (' Type Return to continue to the next folder...')
+1050	FORMAT (' End of folder search.')
+1060	FORMAT (' Type Return to continue...')
+1080	FORMAT(' ',/)
+
+	END
+
+
+
+
+
+	SUBROUTINE SHOW_USER
+C
+C  SUBROUTINE SHOW_USER
+C
+C  FUNCTION: Shows information for specified users.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	DIMENSION NOLOGIN_BTIM(2),START_BTIM(2)
+
+	CHARACTER DATETIME*17
+
+	DIMENSION LAST(2,FOLDER_MAX)
+	INTEGER*2 LAST2(4,FOLDER_MAX)
+	EQUIVALENCE (LAST,LAST2)
+
+	ALL = CLI$PRESENT('NOLOGIN').OR.CLI$PRESENT('ALL')
+     &				.OR.CLI$PRESENT('LOGIN')
+
+	SETPRV = SETPRV_PRIV()		! SETPRV_PRIV rewrites TEMP_USER
+
+	IF (.NOT.ALL) THEN
+	   IER = CLI$GET_VALUE('USERNAME',TEMP_USER)
+	   IF (.NOT.IER) TEMP_USER = USERNAME
+	END IF
+
+	IF (.NOT.SETPRV.AND.(ALL.OR.USERNAME.NE.TEMP_USER)) THEN
+	   WRITE (6,'('' ERROR: No privs to use command.'')')
+	   RETURN
+	END IF
+
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NOLOGIN_BTIM)
+
+	FOLDER_PRESENT = CLI$PRESENT('FOLDER')
+
+	IF (FOLDER_PRESENT) THEN
+	   IER = CLI$GET_VALUE('FOLDER',FOLDER1_NAME)
+	   IF (.NOT.IER) FOLDER1_NAME = FOLDER_NAME
+	   NEWS = INDEX(FOLDER1_NAME,'.').GT.0.OR.(FOLDER1_NAME(:1)
+     &			.GE.'a'.AND.FOLDER1_NAME(:1).LE.'z')
+           IF (.NOT.NEWS) THEN
+	      CALL OPEN_BULLFOLDER_SHARED
+	   ELSE
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL LOWERCASE(FOLDER1_NAME)
+	   END IF
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &				(FOLDER1_NAME(:TRIM(FOLDER1_NAME)),IER)
+	   CALL CLOSE_BULLFOLDER
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR: Folder not found.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	SINCE = CLI$PRESENT('SINCE').OR.CLI$PRESENT('START')
+	IF (CLI$GET_VALUE('SINCE',BULL_PARAMETER,LEN_P)) THEN
+	   IF (.NOT.NEWS) THEN
+	      IER = SYS_BINTIM(BULL_PARAMETER,START_BTIM)
+	      IF (.NOT.IER) THEN
+	         WRITE (6,'('' ERROR: Invalid date specified.'')')
+		 RETURN
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: /SINCE not valid with NEWS group.'')')
+	      RETURN
+	   END IF
+	ELSE IF (CLI$GET_VALUE('START',BULL_PARAMETER,LEN_P)) THEN
+	   IF (NEWS) THEN
+	      IER = OTS$CVT_TI_L(BULL_PARAMETER(:LEN_P),
+     &				    STARTMSG,,%VAL(1))
+	      IF (.NOT.IER) THEN
+		 WRITE (6,'('' ERROR: Invalid number specified.'')')
+		 RETURN
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: /START not valid with folder.'')')
+	      RETURN
+	   END IF
+	ELSE IF (SINCE) THEN
+	   IF (BULL_POINT.EQ.0) THEN
+	      WRITE (6,'('' ERROR: No current message.'')')
+	      RETURN
+	   ELSE IF (NEWS) THEN
+	      STARTMSG = BULL_POINT
+	   ELSE
+	      START_BTIM(1) = MSG_BTIM(1)
+	      START_BTIM(2) = MSG_BTIM(2)
+	   END IF
+	ELSE IF (.NOT.NEWS) THEN
+	   CALL SYS_BINTIM('6-NOV-1956 00:00:00.00',START_BTIM)
+	ELSE
+	   STARTMSG = 1
+	END IF
+
+	CALL DISABLE_CTRL
+	CALL DECLARE_CTRLC_AST
+	IF (FOLDER_PRESENT) THEN
+	   CALL OPEN_BULLINF_SHARED
+	   IER = 0
+	   DO WHILE (IER.EQ.0.AND.FLAG.NE.1)
+	      IF (ALL) THEN
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,IOSTAT=IER) TEMP_USER,LAST
+	         END DO
+	      ELSE
+		 IF (NEWS) THEN
+		    LU = TRIM(TEMP_USER)
+		    TEMP_USER(LU:LU) = CHAR(128.OR.ICHAR(TEMP_USER(LU:LU)))
+		    IF (LU.GT.1) THEN
+		       TEMP_USER(LU-1:LU-1) =
+     &			        CHAR(128.OR.ICHAR(TEMP_USER(LU-1:LU-1)))
+		    ELSE
+		       TEMP_USER(2:2) = CHAR(128.OR.ICHAR(TEMP_USER(2:2)))
+	 	    END IF
+	 	 END IF
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,KEY=TEMP_USER,IOSTAT=IER) TEMP_USER,LAST
+	         END DO
+	      END IF 
+	      UNLOCK 9
+	      IF (IER.EQ.0) THEN
+	         LU = TRIM(TEMP_USER)
+		 I = MAX(LU,2)
+		 DO WHILE (I.GT.0.AND..NOT.BTEST(ICHAR(TEMP_USER(I:I)),7))
+		    I = I - 1
+		 END DO
+		 IF (NEWS.AND.I.GE.LU.AND.I.NE.1.AND.
+     &		     BTEST(ICHAR(TEMP_USER(I-1:I-1)),7)) THEN
+		    TEMP_USER(I:I) = CHAR(ICHAR(TEMP_USER(I:I)).AND.127)
+		    TEMP_USER(I-1:I-1) =
+     &				 CHAR(ICHAR(TEMP_USER(I-1:I-1)).AND.127)
+		    I = 0
+		    NEWSMSG = 1
+		    DO WHILE (LAST2(1,NEWSMSG).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.NEWSMSG.LE.FOLDER_MAX)
+		       NEWSMSG = NEWSMSG + 1
+	            END DO
+		    IF (NEWSMSG.LE.FOLDER_MAX) THEN
+		       FOUND = LAST(2,NEWSMSG).GE.STARTMSG
+		    ELSE
+		       FOUND = .FALSE.
+		    END IF
+		 ELSE IF (.NOT.NEWS.AND.I.EQ.0) THEN
+		    FOUND = COMPARE_BTIM
+     &			(START_BTIM,LAST(1,FOLDER1_NUMBER+1)).LE.0
+		 ELSE
+		    FOUND = .FALSE.
+		 END IF
+		 IF (FOUND.AND.NEWS) THEN
+	            WRITE (6,'(1X,A,'' latest message read '',
+     &			I<LOG10(REAL(LAST(2,NEWSMSG)))+1>,''.'')')
+     &			TEMP_USER(:TRIM(TEMP_USER)),LAST(2,NEWSMSG)
+		 ELSE IF (FOUND) THEN
+		    CALL SYS$ASCTIM(,DATETIME,LAST(1,FOLDER1_NUMBER+1),)
+	            WRITE (6,'(1X,A,'' latest message read '',A,''.'')')
+     &				TEMP_USER(:TRIM(TEMP_USER)),DATETIME
+		 ELSE IF (.NOT.ALL) THEN
+	            WRITE (6,'('' User has never read or not subscribed'',
+     &			'' to specified folder.'')')
+	         END IF
+	      END IF
+	      IF (.NOT.ALL) THEN
+		 IF (IER.NE.0) THEN
+		    WRITE (6,'('' User info does not exist.'')')
+		 END IF
+		 IER = 2
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLINF
+	ELSE IF (.NOT.ALL) THEN
+	   CALL OPEN_BULLUSER_SHARED
+	   CALL READ_USER_FILE_KEYNAME(TEMP_USER,IER)
+	   IF (IER.EQ.0) THEN
+	      IF (COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM).GE.0) THEN
+	         WRITE (6,'('' NOLOGIN set for specified user.'')')
+	      ELSE
+	         CALL SYS$ASCTIM(,DATETIME,LOGIN_BTIM,)
+	         WRITE (6,'('' User last logged in at '',A,''.'')')
+     &						DATETIME
+	      END IF
+	   ELSE
+	      WRITE (6,'('' Entry for specified user not found.'')')
+	   END IF
+	   CALL CLOSE_BULLUSER
+	ELSE
+	   CALL OPEN_BULLUSER_SHARED
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0.AND.FLAG.NE.1)
+	      CALL READ_USER_FILE(IER)
+	      IF (IER.EQ.0.AND.TEMP_USER(:1).NE.':'.AND.
+     &				TEMP_USER(:1).NE.'*') THEN
+		 IER1 = COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM)
+		 IF (.NOT.CLI$PRESENT('LOGIN').AND.IER1.GE.0) THEN
+	            WRITE (6,'('' NOLOGIN set for '',A,''.'')')
+     &					TEMP_USER(:TRIM(TEMP_USER))
+		 ELSE IF (.NOT.CLI$PRESENT('NOLOGIN').AND.IER1.LT.0.AND.
+     &			  COMPARE_BTIM(START_BTIM,LOGIN_BTIM).LE.0) THEN
+	            CALL SYS$ASCTIM(,DATETIME,LOGIN_BTIM,)
+	            WRITE (6,'(1X,A,'' last logged in at '',A,''.'')')
+     &				TEMP_USER(:TRIM(TEMP_USER)),DATETIME
+		 END IF
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLUSER
+	END IF
+	CALL CANCEL_CTRLC_AST
+	CALL ENABLE_CTRL
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE INIT_MESSAGE_ADD(IN_FOLDER,IN_FROM,IN_DESCRIP,IER)
+C
+C  SUBROUTINE INIT_MESSAGE_ADD
+C
+C  FUNCTION:  Opens specified folder in order to add message.
+C
+C  INPUTS:
+C	IN_FOLDER  - Character string containing folder name
+C	IN_FROM	   - Character string containing name of owner of message.
+C		     If empty, the message is searched for either a
+C		     Reply-to: field or a From: field.  If none, then
+C		     the owner of the process is used.  If IN_FROM
+C		     ends with a %, it is assumed that it is simply
+C		     the prefix that should be when responding to the
+C		     address via MAIL.  I.e. the PMDF interface sends
+C		     IN%, so when the From: field is found, the message
+C		     owner becomes IN%"from-address".
+C	IN_DESCRIP - Character string containing subject of message.
+C		     If empty, the message is searched for a line
+C		     which starts with "Subj:" or "Subject:".
+C  OUTPUTS:
+C	IER - Error status.  True if properly connected to folder.
+C		False if folder not found.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BCP/ BULLCP
+	LOGICAL BULLCP
+
+	COMMON /MAIL_PROTOCOL/ PROTOCOL,LPRO
+	CHARACTER*12 PROTOCOL
+	DATA LPRO/0/
+
+	COMMON /DIGEST/ LDESCR,FIRST_BREAK
+
+	CHARACTER*(*) IN_FOLDER,IN_FROM,IN_DESCRIP
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /TEXT_PRESENT/ TEXT
+
+	COMMON /SAVE_IN/ SAVE_IN_DESCRIP,SAVE_IN_FROM
+	CHARACTER*(INPUT_LENGTH) SAVE_IN_DESCRIP,SAVE_IN_FROM
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /OLD_BUFFER/ OLD_BUFFER_FROM,OLD_BUFFER_SUBJ
+	DATA OLD_BUFFER_FROM /.FALSE./, OLD_BUFFER_SUBJ /.FALSE./
+
+	COMMON /SCRTYPE/ SCRTYPE,SCRNAME
+	CHARACTER*132 SCRNAME
+	DATA SCRTYPE/-1/
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+        COMMON /MAIN_FOLDER_DIRECTORY/ FOLDER1_DIRECTORY
+        CHARACTER*80 FOLDER1_DIRECTORY
+
+	IER = LIB$SYS_TRNLOG('BULL_DISABLE',LEN_P,BULL_PARAMETER)
+	IF (IER.EQ.1.AND.LEN_P.GT.0
+     &	    .AND.BULL_PARAMETER(:LEN_P).NE.'ENABLE') CALL SYS$DELPRC(,)
+
+	BULLCP = 1			! Inhibit folder cleanup subprocess
+
+	CALL CHECK_DIR_ACCESS()
+
+	CALL INIT_COMPRESS
+
+	FOLDER1_DIRECTORY = FOLDER_DIRECTORY
+
+	IER = 1
+	DO WHILE (IER.NE.0)
+	   CALL OPEN_BULLFOLDER			! Get folder file
+
+	   CALL READ_FOLDER_FILE_KEYNAME(IN_FOLDER(:TRIM(IN_FOLDER)),IER)
+
+	   CALL CLOSE_BULLFOLDER
+
+	   IF (IER.NE.0) THEN
+	      IER1 = 1
+	      DO WHILE (IER1)
+	         IER2 = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',
+     &			   FOLDER_DIRECTORY)
+	         IF (IER2.AND.FOLDER_DIRECTORY.EQ.FOLDER1_DIRECTORY) THEN 
+		    IER1 = 1
+	         ELSE
+		    IER1 = 0
+		 END IF
+      	      END DO
+	      IF (IER2) THEN
+		 CALL ADD_DIRECTORIES
+	      ELSE
+		 CALL ERRSNS(IDUMMY,IER)
+	         RETURN
+	      END IF
+	   END IF
+	END DO
+	IER = 1
+
+        FOLDER_NAME = FOLDER
+
+	ENTRY INIT_MESSAGE_ADD_BBOARD(IN_FROM,IN_DESCRIP,IER)
+
+	LDESCR = 0
+
+	TEXT = .FALSE.			! No text written, as of yet
+
+	FIRST_BREAK = .TRUE.
+
+	IF (FOLDER_NUMBER.EQ.0) THEN	! If GENERAL folder
+	   FOLDER_SET = .FALSE.		! indicate it
+	ELSE				! Else it's another folder
+	   FOLDER_SET = .TRUE.		! indicate it
+	END IF
+
+	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		FOLDER			! set folder file names
+
+	ENTRY INIT_MESSAGE_ADD_DIGEST(IN_FROM,IN_DESCRIP,IER)
+
+	CALL OPEN_BULLDIR		! Open directory file
+
+	CALL OPEN_BULLFIL		! Open data file
+
+	CALL READDIR(0,IER1)		! Get NBLOCK
+	IF (IER1.EQ.0) NBLOCK = 0	! If new file, NBLOCK is 0
+
+	NBLOCK = NBLOCK + 1
+	LENGTH = NBLOCK			! Initialize line count
+	IF (NEWS_FEED()) THEN
+	   CALL STRIP_HEADER(' ',-1,IER)
+	END IF
+
+	LEN_FROM = TRIM(IN_FROM)
+
+	IF (IN_FROM(LEN_FROM:LEN_FROM).EQ.'%') THEN	! Just protocol
+	   PROTOCOL = IN_FROM(:LEN_FROM)//'"'
+	   LPRO = LEN_FROM + 1
+	   LEN_FROM = 0
+	END IF
+
+	MAIL = BTEST(FOLDER_FLAG,11).AND.INDEX(FOLDER_DESCRIP,'<').GT.0
+	IF (MAIL) THEN 
+	   SCRNAME = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//'BULL.MAIL'
+	   OPEN (UNIT=3,DISPOSE='DELETE',FILE=SCRNAME,
+     &	    FORM='FORMATTED',RECL=LINE_LENGTH,IOSTAT=IER1,STATUS='NEW')
+	   SCRTYPE = 0
+	   SAVE_IN_DESCRIP = IN_DESCRIP
+	   SAVE_IN_FROM = ' '
+	ELSE IF (NEWS_FEED().OR.LEN_FROM.EQ.0
+     &		.OR.(BTEST(FOLDER_FLAG,5).AND.FIRST_BREAK)) THEN
+	   SCRTYPE = 0
+	   SCRNAME = 'SYS$LOGIN:BULL.SCR'
+	   OPEN (UNIT=3,DISPOSE='DELETE',FILE=SCRNAME,
+     &	    FORM='FORMATTED',RECL=LINE_LENGTH,IOSTAT=IER1,STATUS='NEW')
+	   IF (IER1.NE.0) THEN
+	      SCRNAME = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//'BULL.SCR'
+	      OPEN (UNIT=3,DISPOSE='DELETE',FILE=SCRNAME,
+     &		FORM='FORMATTED',RECL=LINE_LENGTH,STATUS='NEW')
+	   END IF
+	   SAVE_IN_DESCRIP = IN_DESCRIP
+	   SAVE_IN_FROM = ' '
+	END IF
+
+	IF (LEN_FROM.GT.0) THEN
+	   INFROM = IN_FROM
+	   IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	      CALL STORE_FROM(INFROM,LEN_FROM)
+	   ELSE	IF (INDEX(INFROM,'%"').GT.0) THEN	! Store any protocol
+	      LPRO = INDEX(INFROM,'%"') + 1
+	      PROTOCOL = INFROM(:LPRO)
+	   END IF
+	   LEN_DESCRP = TRIM(IN_DESCRIP)
+	   IF (LEN_DESCRP.GT.0) THEN
+	      INDESCRIP = IN_DESCRIP
+	      IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	         CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	      END IF
+	   ELSE
+	      DESCRIP = ' '
+	   END IF
+	END IF
+
+	OLD_BUFFER = ' '
+
+	OLD_BUFFER_SUBJ = .FALSE.
+	OLD_BUFFER_FROM = .FALSE.
+
+	INEXDATE = .FALSE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE WRITEOUT_STORED
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /STORED/ STORED
+
+	CHARACTER*256 BUFFER
+
+	REWIND (UNIT=3)
+
+      	IER = 0
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(A)',IOSTAT=IER) BUFFER
+	   IF (IER.EQ.0) THEN
+	      CALL WRITE_MESSAGE_LINE(BUFFER)
+	   END IF
+	END DO
+
+	IF (BTEST(FOLDER_FLAG,5)) RETURN
+	IF (.NOT.NEWS_FEED().AND.
+     &	    .NOT.BTEST(FOLDER_FLAG,11).AND..NOT.STORED) CLOSE (UNIT=3)
+        IF (BTEST(FOLDER_FLAG,11)) REWIND (UNIT=3)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE WRITE_MESSAGE_LINE(BUFFER)
+C
+C  SUBROUTINE WRITE_MESSAGE_LINE
+C
+C  FUNCTION:  Writes one line of message into folder.
+C
+C  INPUTS:
+C	BUFFER - Character string containing line to be put into message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /MAIL_PROTOCOL/ PROTOCOL,LPRO
+	CHARACTER*12 PROTOCOL
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /DIGEST/ LDESCR,FIRST_BREAK
+	DATA FIRST_BREAK/.TRUE./
+
+	COMMON /TEXT_PRESENT/ TEXT
+
+	COMMON /SAVE_IN/ SAVE_IN_DESCRIP,SAVE_IN_FROM
+	CHARACTER*(INPUT_LENGTH) SAVE_IN_DESCRIP,SAVE_IN_FROM
+
+	CHARACTER*(*) BUFFER
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /OLD_BUFFER/ OLD_BUFFER_FROM,OLD_BUFFER_SUBJ
+
+	COMMON /DATE/ DATE_LINE
+	CHARACTER*(INPUT_LENGTH) DATE_LINE
+
+	CHARACTER*24 TODAY
+
+	COMMON /STORED/ STORED
+	DATA STORED /.FALSE./ 
+
+	LEN_BUFFER = TRIM(BUFFER)
+
+	IF (LEN_FROM.EQ.0) THEN
+	   WRITE (3,'(A)') BUFFER(:MIN(LEN_BUFFER,LINE_LENGTH))
+	   IF (LEN_BUFFER.GT.LINE_LENGTH) THEN
+	      WRITE (3,'(A)') ' '//BUFFER(LINE_LENGTH+1:LEN_BUFFER)
+	   END IF
+	   IF (OLD_BUFFER_FROM.AND.(BUFFER(:1).EQ.' '.OR.
+     &		BUFFER(:1).EQ.CHAR(9)).AND.LEN_BUFFER.GT.1) THEN
+	      SAVE_IN_FROM = 
+     &		SAVE_IN_FROM(:TRIM(SAVE_IN_FROM))//BUFFER(:LEN_BUFFER)
+	      RETURN
+	   ELSE IF (OLD_BUFFER_SUBJ.AND.(BUFFER(:1).EQ.' '.OR.
+     &		BUFFER(:1).EQ.CHAR(9)).AND.LEN_BUFFER.GT.1) THEN
+	      INDESCRIP = 
+     &		INDESCRIP(:TRIM(INDESCRIP))//BUFFER(:LEN_BUFFER)
+	      LDESCR = LDESCR + LEN_BUFFER
+	      RETURN
+	   ELSE IF (BUFFER(:5).EQ.'From:'.AND.SAVE_IN_FROM.EQ.' ') THEN
+	      IF (LEN_BUFFER.GE.7) SAVE_IN_FROM = BUFFER(7:)
+	      OLD_BUFFER_FROM = .TRUE.
+	      OLD_BUFFER_SUBJ = .FALSE.
+	      RETURN
+	   ELSE IF (BUFFER(:9).EQ.'Subject: ') THEN
+	      LDESCR = LEN_BUFFER - 9
+	      INDESCRIP = BUFFER(10:)
+	      OLD_BUFFER_SUBJ = .TRUE.
+	      OLD_BUFFER_FROM = .FALSE.
+	      RETURN
+	   ELSE IF (BUFFER(:9).EQ.'Reply-To:') THEN
+	      IF (LEN_BUFFER.GE.11) SAVE_IN_FROM = BUFFER(11:)
+	      OLD_BUFFER_FROM = .TRUE.
+	      OLD_BUFFER_SUBJ = .FALSE.
+	      RETURN
+	   ELSE IF (LEN_BUFFER.EQ.0) THEN
+	      IF (SAVE_IN_FROM.EQ.' ') CALL GETUSER(SAVE_IN_FROM)
+	      LEN_FROM = TRIM(SAVE_IN_FROM)
+	      IF (LEN_FROM.GT.0) THEN
+		 OLD_BUFFER_FROM = .FALSE.
+		 INFROM = SAVE_IN_FROM
+		 IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+		    CALL STORE_FROM(INFROM,LEN_FROM)
+		 ELSE IF (INDEX(INFROM,'%"').GT.0) THEN
+		    LPRO = INDEX(INFROM,'%"') + 1
+		    PROTOCOL = INFROM(:LPRO)
+		 END IF
+		 IF (LDESCR.GT.0) THEN
+		    LEN_DESCRP = LDESCR
+	            CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+		 ELSE
+	            LEN_DESCRP = TRIM(SAVE_IN_DESCRIP)
+	            IF (LEN_DESCRP.GT.0) THEN
+	               INDESCRIP = SAVE_IN_DESCRIP
+	               IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	                  CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	               END IF
+	            ELSE
+		       INDESCRIP = ' '
+		       DESCRIP = ' '
+		    END IF
+		 END IF
+	         STORED = .TRUE.
+	         IF (.NOT.BTEST(FOLDER_FLAG,5)) CALL WRITEOUT_STORED
+	         STORED = .FALSE.
+	      END IF
+	   END IF
+	   OLD_BUFFER_FROM = .FALSE.
+	   OLD_BUFFER_SUBJ = .FALSE.
+	   RETURN
+	END IF
+	IF (BTEST(FOLDER_FLAG,5)) THEN
+	   IF (INDEX(BUFFER,'-------------').EQ.1) THEN
+	      BREAK = .TRUE.
+	      DO I=1,LEN_BUFFER
+		 IF (BUFFER(I:I).NE.'-') BREAK = .FALSE.
+	      END DO
+	   ELSE
+	      BREAK = .FALSE.
+	   END IF
+	   IF (BREAK) THEN
+	      IF (.NOT.FIRST_BREAK) THEN
+		 CALL FINISH_MESSAGE_ADD
+	         CALL INIT_MESSAGE_ADD_DIGEST(INFROM,INDESCRIP,IER)
+	      ELSE
+		 FIRST_BREAK = .FALSE.
+                 CLOSE (UNIT=3)
+	      END IF
+	      LFROM = 0
+	      LDESCR = 0
+	      RETURN
+	   ELSE IF (.NOT.FIRST_BREAK) THEN
+	      IF (LDESCR.EQ.0) THEN
+	         IF (BUFFER(:9).EQ.'Subject: ') THEN
+		    LDESCR = LEN_BUFFER - 9
+	            CALL STORE_DESCRP(BUFFER(10:),LDESCR)
+		    IF (LFROM.EQ.0) THEN
+		       LFROM = LEN_FROM
+	               CALL STORE_FROM(INFROM,LFROM)
+		    END IF
+		 ELSE IF (BUFFER(:6).EQ.'From: ') THEN
+		    LFROM = LEN_BUFFER - 6
+		    IF (LFROM.LE.0) THEN
+		       LFROM = TRIM(SAVE_IN_FROM)
+		       IF (LPRO.GT.0) THEN
+		          LFROM = LFROM + LPRO + 1
+	                  CALL STORE_FROM(PROTOCOL(:LPRO)//
+     &			   SAVE_IN_FROM//'"',LFROM)
+		       ELSE
+	                  CALL STORE_FROM(SAVE_IN_FROM,LFROM)
+		       END IF
+		    ELSE IF (LPRO.GT.0) THEN
+		       LFROM = LFROM + LPRO + 1
+	               CALL STORE_FROM(PROTOCOL(:LPRO)//
+     &			BUFFER(7:LEN_BUFFER)//'"',LFROM)
+		    ELSE
+	               CALL STORE_FROM(BUFFER(7:),LFROM)
+		    END IF
+		 END IF
+		 RETURN
+	      END IF
+	   ELSE
+	      IF (LEN_BUFFER.GT.0) THEN
+		 IF (.NOT.TEXT) THEN
+	            IF (.NOT.NEWS_FEED()) THEN
+		       TEXT = .TRUE.
+		    ELSE
+	               CALL STRIP_HEADER(BUFFER,TRIM(BUFFER),IER)
+		       TEXT = .NOT.IER
+		    END IF
+		 END IF
+		 IF (TEXT) THEN
+	            WRITE (3,'(A)') BUFFER(:MIN(LEN_BUFFER,LINE_LENGTH))
+		 END IF
+	      ELSE
+		 IF (TEXT) WRITE (3,'(A)') ' '
+	      END IF
+	      RETURN
+	   END IF
+	END IF
+
+	IF (LEN_BUFFER.EQ.0) THEN		! If empty line
+	   IF (.NOT.STORED.AND.
+     &	       ((TEXT.AND.NEWS_FEED()).OR.BTEST(FOLDER_FLAG,11))) THEN
+	      WRITE (3,'(A)') ' '
+	      CALL STRIP_HEADER(' ',-1,IER)
+	   END IF
+	   CALL STORE_BULL(1,' ',NBLOCK)
+	ELSE
+	   IF (LEN_DESCRP.EQ.0) THEN
+	      IF (BUFFER(:9).EQ.'Subject: ') THEN
+		 DESCRIP = BUFFER(INDEX(BUFFER,' ')+1:)
+		 LEN_DESCRP = LEN_BUFFER
+	      END IF
+	   END IF
+	   IF (.NOT.INEXDATE) THEN
+	      IF (BUFFER(:9).EQ.'Expires: '.OR.
+     &		  BUFFER(:11).EQ.'X-Expires: ') THEN
+		 I = INDEX(BUFFER,' ')+1
+		 NODATE = .FALSE.
+		 DO J=I,LEN_BUFFER
+		    IF (BUFFER(J:J).EQ.','.OR.BUFFER(J:J).EQ.'-') THEN
+		       BUFFER(J:J) = ' '
+		    END IF
+		 END DO
+	         CALL STR$UPCASE(BUFFER(I:),BUFFER(I:))
+		 NODATE = .TRUE.
+		 I = INDEX(BUFFER,' ')+1
+		 EXDATE(3:3) = '-'
+		 EXDATE(7:7) = '-'
+		 DO WHILE (I.LE.LEN_BUFFER)
+		    IF (BUFFER(I:I).GE.'0'.AND.BUFFER(I:I).LE.'9') THEN
+		       IF (NODATE) THEN
+			  IF (INDEX(BUFFER(I:),' ').EQ.2) THEN
+			     EXDATE(1:2) = '0'//BUFFER(I:I)
+			     I = I + 1
+			  ELSE
+			     EXDATE(1:2) = BUFFER(I:I+1)
+			     I = I + 2
+			  END IF
+			  NODATE = .FALSE.
+		       ELSE
+			  IF (LEN_BUFFER-I.EQ.1.OR.
+     &			     INDEX(BUFFER(I:),' ').EQ.3) THEN   ! No century?
+			     IER = SYS$ASCTIM(,TODAY,,)	   ! Get today's date
+			     YEAR = INDEX(TODAY(6:),'-')
+			     EXDATE(8:) = TODAY(6+YEAR:7+YEAR)//BUFFER(I:I+1)
+			     I = I + 2
+			  ELSE
+			     EXDATE(8:) = BUFFER(I:I+3)
+			     I = I + 4
+			  END IF
+		       END IF
+		    ELSE IF (BUFFER(I:I).GE.'A'.AND.BUFFER(I:I).LE.'Z') THEN
+		       EXDATE(4:6) = BUFFER(I:I+2)
+		       I = I + 3
+		    ELSE
+		       I = I + 1
+		    END IF
+		 END DO
+		 INEXDATE = .TRUE.
+	      END IF
+	   END IF
+	   CALL STORE_BULL(MIN(LEN_BUFFER,LINE_LENGTH),BUFFER,NBLOCK)
+	   IF (NEWS_FEED().AND..NOT.TEXT) THEN
+	      CALL STRIP_HEADER(BUFFER,TRIM(BUFFER),IER)
+	      TEXT = .NOT.IER
+	   ELSE
+	      TEXT = .TRUE.
+           END IF
+	   IF (.NOT.STORED.AND.
+     &	       ((TEXT.AND.NEWS_FEED()).OR.BTEST(FOLDER_FLAG,11))) THEN
+	      WRITE (3,'(A)') BUFFER(:MIN(LEN_BUFFER,LINE_LENGTH))
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FINISH_MESSAGE_ADD
+C
+C  SUBROUTINE FINISH_MESSAGE_ADD
+C
+C  FUNCTION:  Writes message entry into directory file and closes folder
+C
+C  NOTE:  Only should be run if INIT_MESSAGE_ADD was successful.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /DIGEST/ LDESCR,FIRST_BREAK
+
+	COMMON /SCRTYPE/ SCRTYPE,SCRNAME
+	CHARACTER*132 SCRNAME
+
+	COMMON /TEXT_PRESENT/ TEXT
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /SAVE_IN/ SAVE_IN_DESCRIP,SAVE_IN_FROM
+	CHARACTER*(INPUT_LENGTH) SAVE_IN_DESCRIP,SAVE_IN_FROM
+
+	CHARACTER*24 TODAY
+
+	CHARACTER USER_SAVE*12,PROC_SAVE*12
+
+	DIMENSION BIN_EXTIME(2)
+
+	IF (TEXT.AND.BTEST(FOLDER_FLAG,5).AND.FIRST_BREAK) THEN
+	   IF (LEN_FROM.GT.0) THEN
+	      CALL STORE_FROM(INFROM,LEN_FROM)
+	   ELSE
+	      CALL GETUSER(FROM)
+	      INFROM = FROM
+	      LEN_FROM = TRIM(INFROM)
+	   END IF
+	   IF (LEN_DESCRP.GT.0) THEN
+	      CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	   END IF
+	   LDESCRP = 1
+	   FIRST_BREAK = .FALSE.
+	   CALL WRITEOUT_STORED
+	   CLOSE (UNIT=3)
+	ELSE IF (LEN_FROM.EQ.0) THEN
+	   CALL GETUSER(FROM)
+	   INFROM = FROM
+	   LEN_FROM = TRIM(INFROM)
+	   LEN_DESCRP = TRIM(SAVE_IN_DESCRIP)
+	   IF (LEN_DESCRP.GT.0) THEN
+	      INDESCRIP = SAVE_IN_DESCRIP
+	      IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	         CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	      END IF
+	   ELSE
+	      INDESCRIP = ' '
+	      DESCRIP = ' '
+	   END IF
+	   CALL WRITEOUT_STORED
+	END IF
+
+	CALL FLUSH_BULL(NBLOCK)
+
+	CALL CLOSE_BULLFIL			! Finished adding bulletin
+
+	IF ((BTEST(FOLDER_FLAG,5).AND.LDESCR.EQ.0).OR.	! End of digest msg
+     &				.NOT.TEXT) THEN	! or no message text found
+	   CALL CLOSE_BULLDIR			! then don't add message entry
+	   IF (SCRTYPE.EQ.0) THEN
+	      CLOSE (UNIT=3)
+              SCRTYPE = -1
+	   END IF
+	   RETURN
+	END IF
+
+	EXTIME = '00:00:00.00'
+	IF (INEXDATE) THEN
+	   IER = SYS_BINTIM(EXDATE//' '//EXTIME,BIN_EXTIME)
+	   IF (IER) THEN			! If good date format
+	      IER = SYS$ASCTIM(,TODAY,,)	! Get today's date
+	      IER = COMPARE_DATE(EXDATE,TODAY(:11)) ! Compare date with today's
+	      IF ((IER.GT.F_EXPIRE_LIMIT.AND.F_EXPIRE_LIMIT.GT.0) ! Too great?
+     &		.OR.IER.LE.0) THEN		! or expiration date not future
+	         INEXDATE = .FALSE.		! Don't use it
+	      END IF
+	   ELSE
+	      INEXDATE = .FALSE.		! Don't use it
+	   END IF
+	END IF
+
+	IF (.NOT.INEXDATE) THEN
+	   IF (FOLDER_BBEXPIRE.EQ.-1) THEN	! Folder has expiration time?
+	      EXDATE = '5-NOV-2100'		! no, so set date far in future
+	      SYSTEM = 2			! indicate permanent message
+	   ELSE					! Else set expiration date
+	      CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      SYSTEM = 0
+	   END IF
+	END IF
+
+	LENGTH = NBLOCK - LENGTH + 1		! Number of records
+
+	CALL ADD_ENTRY				! Add the new directory entry
+
+	CALL CLOSE_BULLDIR			! Totally finished with add
+
+	CALL UPDATE_FOLDER
+
+	IF (SCRTYPE.EQ.0.AND.NEWS_FEED()) THEN
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,'<')+1:)
+	   FOLDER1_DESCRIP = FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,'>')-1)
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+      	   CALL NEWS_POST('ignore',.TRUE.,IER,INDESCRIP)
+	   IF (.NOT.BTEST(FOLDER_FLAG,11)) CLOSE (UNIT=3)
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,11).AND.SCRTYPE.EQ.0) THEN
+	   IF (NEWS_FEED()) THEN
+	      SLIST = INDEX(FOLDER_DESCRIP,'[')
+	   ELSE
+	      SLIST = INDEX(FOLDER_DESCRIP,'<')
+	   END IF
+	   IF (SLIST.GT.0) THEN
+	      INPUT = FOLDER_DESCRIP(SLIST+1:)
+	      IF (NEWS_FEED()) THEN
+	         ILEN = INDEX(INPUT,']') - 1
+	      ELSE
+	         ILEN = INDEX(INPUT,'>') - 1
+	      END IF
+	      IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+	      INPUT = INPUT(:ILEN)
+              CALL ADD_PROTOCOL(INPUT,ILEN)
+	      CLOSE (UNIT=3,STATUS='SAVE')
+	      CALL GETUSER(PROC_SAVE)
+              USER_SAVE = USERNAME
+	      USERNAME = FOLDER
+	      IF (CONFIRM_USER(USERNAME).EQ.0) THEN
+	        CALL SETUSER(USERNAME)
+	      END IF
+	      IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED')) THEN
+	         IER = LIB$SET_LOGICAL
+     &			('MX_REPLY_TO',INFROM(:TRIM(INFROM)))
+	      ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED')) THEN 
+	         IER = LIB$SET_LOGICAL
+     &			('PMDF_REPLY_TO',INFROM(:TRIM(INFROM)))
+	      ELSE IF (FOLDER1_BBOARD(:4).NE.'NONE') THEN
+		 USERNAME = FOLDER_BBOARD
+	      END IF
+	      IF (.NOT.BTEST(FOLDER_FLAG,15)) THEN 
+	         CALL RESPOND_MAIL(SCRNAME,INPUT,
+     &	   	    FOLDER(:TRIM(FOLDER))//' folder message: '//
+     &	   	    INDESCRIP(:LEN_DESCRP),STATUS)
+	      ELSE
+	         CALL RESPOND_MAIL(SCRNAME,INPUT,
+     &	   	    INDESCRIP(:LEN_DESCRP),STATUS)
+	      END IF
+              CALL LIB$DELETE_FILE(SCRNAME(:TRIM(SCRNAME))//';*')
+	      CALL SETUSER(PROC_SAVE)
+	      USERNAME = USER_SAVE
+	   ELSE
+	      CLOSE (UNIT=3)
+	   END IF
+	ELSE IF (SCRTYPE.EQ.0) THEN
+	   CLOSE (UNIT=3)
+	END IF
+
+	CALL STRIP_HEADER(' ',-1,IER)
+
+	SCRTYPE = -1
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_FROM(IFROM,LEN_INFROM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MAIL_PROTOCOL/ PROTOCOL,LPRO
+	CHARACTER*12 PROTOCOL
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(*) IFROM
+
+	CHARACTER*(INPUT_LENGTH) INFROM
+
+	INFROM = IFROM
+
+	IF (LPRO.GT.0) THEN			! Protocol present?
+	   I = INDEX(INFROM,'%"') + 2		! Make usable for VMS MAIL
+	   IF (I.EQ.2) THEN
+	      INFROM = PROTOCOL(:LPRO)//INFROM(:LEN_INFROM)//'"'
+	      I = LPRO + 1
+	      LEN_INFROM = LEN_INFROM + LPRO + 1
+	   END IF
+	   DO WHILE (I.LT.LEN_INFROM)
+	      IF (INFROM(I:I).EQ.'"') THEN
+		 INFROM(I:I) = ''''
+	      ELSE IF (INFROM(I:I).EQ.'\') THEN
+		 INFROM(I+1:) = '\'//INFROM(I+1:)
+		 LEN_INFROM = LEN_INFROM + 1
+		 I = I + 1
+	      ELSE IF (INFROM(I:I).EQ.''''.AND.
+     &		       INDEX(INFROM,'@').GT.I) THEN
+		 INFROM(I:) = '\s'//INFROM(I+1:)
+		 LEN_INFROM = LEN_INFROM + 1
+		 I = I + 2
+	      END IF
+	      I = I + 1
+	   END DO
+	END IF
+
+	DO I=1,LEN_INFROM			! Remove control characters
+	   IF (INFROM(I:I).LT.' ') INFROM(I:I) = ' '
+	END DO
+
+	DO WHILE (LEN_INFROM.GT.0.AND.INFROM(:1).EQ.' ')
+	   INFROM = INFROM(2:)
+	   LEN_INFROM = LEN_INFROM - 1
+	END DO
+
+	TWO_SPACE = INDEX(INFROM,'  ')
+	DO WHILE (TWO_SPACE.GT.0.AND.TWO_SPACE.LT.LEN_INFROM)
+	   INFROM = INFROM(:TWO_SPACE)//INFROM(TWO_SPACE+2:)
+	   LEN_INFROM = LEN_INFROM - 1
+	   TWO_SPACE = INDEX(INFROM,'  ')
+	END DO
+
+C	IF (.NOT.NEWS_FEED()) THEN
+           CALL STORE_BULL(6+LEN_INFROM,'From: '//INFROM(:LEN_INFROM),
+     &		NBLOCK)
+C	END IF
+
+	IF (INDEX(INFROM,'%"').GT.0)		! Strip off protocol program
+     &		INFROM = INFROM(INDEX(INFROM,'%"')+2:)
+
+	IF (INDEX(INFROM,'::').GT.0)		! Strip off node name
+     &		INFROM = INFROM(INDEX(INFROM,'::')+2:)	! I.e. HOST::USER
+
+	CALL GET_FROM(FROM,INFROM,LEN_INFROM)
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_FROM(FROM,INFROM1,LEN_INFROM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INFROM1,FROM
+
+	CHARACTER*256 INFROM
+
+	INFROM = INFROM1
+
+	DO WHILE (INDEX(INFROM,'!').GT.0.AND.	! Unix address go backwards.
+     &		INDEX(INFROM,'!').LT.INDEX(INFROM,'@'))
+	   INFROM = INFROM(INDEX(INFROM,'!')+1:)	! I.e. host!user
+	END DO
+
+	I = INDEX(INFROM,'<')
+	IF (I.GT.0.AND.INDEX(INFROM(I+1:),'@').GT.0) THEN ! Name may be of form
+	   INFROM = INFROM(INDEX(INFROM,'<')+1:)   ! personal-name <net-name>
+	END IF
+
+	I = INDEX(INFROM,'(')
+	IF (I.GT.0.AND.INDEX(INFROM(I+1:),'@').GT.0) THEN ! Name may be of form
+	   INFROM = INFROM(INDEX(INFROM,'(')+1:)   ! personal-name (net-name)
+	END IF
+
+	I = 1	! Trim username to start at first alpha character
+	DO WHILE (I.LE.LEN_INFROM.AND.(INFROM(I:I).EQ.' '.OR.
+     &		INFROM(I:I).EQ.'%'.OR.INFROM(I:I).EQ.'.'.OR.
+     &		INFROM(I:I).EQ.'@'.OR.INFROM(I:I).EQ.'<'.OR.
+     &		INFROM(I:I).EQ.'\'.OR.INFROM(I:I).LE.' '.OR.
+     &		INFROM(I:I).GE.CHAR(127).OR.
+     &		INFROM(I:I).EQ.'"'.OR.INFROM(I:I).EQ.''''))
+	   I = I + 1
+	END DO
+	INFROM = INFROM(I:)
+	J = LEN_INFROM - I + 1
+
+	I = 1		! Trim username to end at a alpha character
+	DO WHILE (I.LE.J.AND.INFROM(I:I).NE.' '.AND.
+     &		INFROM(I:I).NE.'%'.AND.
+     &		INFROM(I:I).NE.'@'.AND.INFROM(I:I).NE.'<'.AND.
+     &		INFROM(I:I).NE.'\'.AND.INFROM(I:I).GT.' '.AND.
+     &		INFROM(I:I).LT.CHAR(127).AND.
+     &		INFROM(I:I).NE.'"'.AND.INFROM(I:I).NE.'''')
+	   I = I + 1
+	END DO
+	FROM = INFROM(:I-1)
+
+	DO J=2,TRIM(FROM)
+	   IF ((FROM(J:J).GE.'A'.AND.FROM(J:J).LE.'Z').AND.
+     &	       ((FROM(J-1:J-1).GE.'A'.AND.FROM(J-1:J-1).LE.'Z').OR.
+     &	        (FROM(J-1:J-1).GE.'a'.AND.FROM(J-1:J-1).LE.'z'))) THEN
+	      FROM(J:J) = CHAR(ICHAR(FROM(J:J))-ICHAR('A')+ICHAR('a'))
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(*) INDESCRIP
+
+	CALL CONVERT_TABS(INDESCRIP,LEN_DESCRP)
+
+	DO I=1,LEN_DESCRP			! Remove control characters
+	   IF (INDESCRIP(I:I).LT.' '.OR.ICHAR(INDESCRIP(I:I)).GT.126)
+     &			INDESCRIP(I:I) = ' '
+	END DO
+
+	DO WHILE (LEN_DESCRP.GT.0.AND.INDESCRIP(:1).EQ.' ')
+	   INDESCRIP = INDESCRIP(2:)
+	   LEN_DESCRP = LEN_DESCRP - 1
+	END DO
+
+	IF (LEN_DESCRP.GT.LEN(DESCRIP)) THEN
+C	IF (LEN_DESCRP.GT.LEN(DESCRIP).AND..NOT.NEWS_FEED()) THEN
+				! Is length > allowable subject length?
+	   CALL STORE_BULL(6+LEN_DESCRP,'Subj: '//
+     &		INDESCRIP(:LEN_DESCRP),NBLOCK)
+	END IF
+
+	DESCRIP = INDESCRIP(:MIN(LEN_DESCRP,LEN(DESCRIP)))
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE STRIP_HEADER(BUFFER,BLEN,IER)
+C
+C  SUBROUTINE STRIP_HEADER
+C
+C  FUNCTION:  Indicates whether line is part of mail message header.
+C
+C  INPUTS:
+C	BUFFER	- Character string containing input line of message.
+C	BLEN	- Length of character string.  If = 0, initialize subroutine.
+C
+C  OUTPUTS:
+C	IER	- If true, line should be stripped.  Else, end of header.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /DATE/ DATE_LINE
+	CHARACTER*(INPUT_LENGTH) DATE_LINE
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+	DATA HEADER_Q1/0/
+
+	CHARACTER*(*) BUFFER
+
+	IF (TRIM(BUFFER).EQ.0) THEN
+			! If STRIP not set for folder or empty line
+	   IER = .FALSE.
+	   CONT_LINE = .FALSE.
+	   LAST_NEWSGROUPS = .FALSE.
+	   CALL INIT_QUEUE(HEADER_Q1,INPUT)
+	   IF (BLEN.EQ.-1) THEN
+	      CALL INIT_QUEUE(HEADER_Q1,INPUT)
+	      HEADER_Q = HEADER_Q1
+	      NHEAD = 0
+	   END IF
+	   RETURN
+	END IF
+
+	IF (BLEN.EQ.0) THEN
+	   DATE_LINE = ' '
+	   CONT_LINE = .FALSE.
+	   LAST_NEWSGROUPS = .FALSE.
+	END IF
+
+	IER = .TRUE.
+
+	IF (CONT_LINE.AND.(BUFFER(:1).EQ.' '.OR.   ! If line is continuation
+     &		BUFFER(:1).EQ.CHAR(9))) THEN	   ! of previous header line
+	   IF (LAST_NEWSGROUPS) THEN
+	      NEWSGROUPS = NEWSGROUPS(:TRIM(NEWSGROUPS))//BUFFER(2:)
+	   END IF
+	   CALL WRITE_QUEUE(%VAL(HEADER_Q),HEADER_Q,BUFFER)
+	   NHEAD = NHEAD + 1
+	   RETURN
+	END IF
+
+	I = 1
+	DO WHILE (I.LE.BLEN.AND.BUFFER(I:I).NE.' ')
+	   IF (BUFFER(I:I).EQ.':') THEN	! Header line found
+	      CONT_LINE = .TRUE.	! Next line might be continuation
+	      LAST_NEWSGROUPS = .FALSE.
+	      IF (REMOTE_SET.LT.3.AND.BUFFER(:5).EQ.'Date:') THEN
+		 DATE_LINE = 'Message sent'//BUFFER(5:BLEN)
+		 IF (DATE_LINE(TRIM(DATE_LINE):).NE.'.') THEN
+		    DATE_LINE(TRIM(DATE_LINE)+1:) = '.'
+	         END IF
+	      ELSE IF (BUFFER(:11).EQ.'Newsgroups:') THEN
+		 NEWSGROUPS = BUFFER(13:)
+		 LAST_NEWSGROUPS = .TRUE.
+	      END IF
+	      CALL WRITE_QUEUE(%VAL(HEADER_Q),HEADER_Q,BUFFER)
+	      NHEAD = NHEAD + 1
+	      RETURN
+	   ELSE
+	      I = I + 1
+	   END IF
+	END DO
+
+	IER = .FALSE.
+	CONT_LINE = .FALSE.
+	LAST_NEWSGROUPS = .FALSE.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_NEWS_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+C
+C  SUBROUTINE SET_NEWS_FOLDER_DEFAULT
+C
+C  FUNCTION: Sets flag defaults for specified news group
+C	Note: If NOTIFY READNEW and BRIEF = 0, it is either news 
+C	group removal or SET SUBSCRIBE command.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_NEGATED
+
+	ALL = .FALSE.
+	DEFAULT = 1
+        NODEFAULT = 0
+	SUB = ABS(BRIEF)+ABS(NOTIFY)+ABS(READNEW).EQ.0
+
+	IF (NOTIFY.EQ.1.AND.REMOTE_SET.EQ.3) THEN
+	   WRITE (6,'('' ERROR: /NOTIFY is invalid with non-stored'',
+     &		  '' news group.'')')
+           RETURN
+	END IF
+
+	IF (INCMD(:3).EQ.'SET') THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	      WRITE (6,'(
+     &           '' ERROR: Privileges needed for changing defaults.'')')
+	      RETURN
+	   END IF
+	   ALL = CLI$PRESENT('ALL')
+	   DEFAULT = CLI$PRESENT('DEFAULT')
+	   NODEFAULT = CLI$PRESENT('NODEFAULT')
+	   CALL OPEN_BULLNEWS_SHARED
+	   CALL OPEN_BULLINF_SHARED
+	   IF (CLI$PRESENT('NOPERMANENT').OR.CLI$PRESENT('PERMANENT').OR.
+     &	     	(SUB.AND.(NODEFAULT.OR.CLI$PRESENT('NOPERMANENT')))) THEN
+              DO WHILE (REC_LOCK(IER1))
+                 READ (9,KEY='*PERM',IOSTAT=IER1) TEMP_USER,INF_REC
+	      END DO
+	      IF (IER1.NE.0) THEN
+                 DO I=1,FOLDER_MAX
+                    INF_REC(1,I) = 0
+                    INF_REC(2,I) = 0
+                 END DO
+              END IF
+
+              IF (CLI$PRESENT('PERMANENT')) THEN
+                 CALL SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+		 IF (SUB) DEFAULT = 1
+              ELSE IF (CLI$PRESENT('NOPERMANENT').OR.NODEFAULT) THEN
+                 IF (NOTIFY.GE.0) CALL SET_NEWS_FLAG(IER,0,-1,-1)
+                 IF (READNEW.GE.0.OR.BRIEF.GE.0)
+     &	 		CALL SET_NEWS_FLAG(IER,-1,0,0)
+		 IF (SUB)
+     &			CALL SET_NEWS_FLAG(IER,-1,-1,-1)
+              END IF
+              IF (.NOT.IER) THEN
+                 CALL CLOSE_BULLNEWS
+                 CALL CLOSE_BULLINF
+                 RETURN
+              END IF
+              IF (IER1.EQ.0) THEN
+                 REWRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+              ELSE
+                 WRITE (9,IOSTAT=IER) '*PERM       ',INF_REC
+              END IF
+           END IF	
+	ELSE
+ 	   CALL OPEN_BULLNEWS_SHARED
+ 	   CALL OPEN_BULLINF_SHARED
+	END IF
+
+        DO WHILE (REC_LOCK(IER1))
+           READ (9,KEY='*DEFAULT',IOSTAT=IER1) TEMP_USER,INF_REC
+	END DO
+	IF (IER1.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      INF_REC(1,I) = 0
+	      INF_REC(2,I) = 0
+	   END DO
+	END IF
+        IF (NODEFAULT.AND.SUB) THEN
+	   NOTIFY = -1
+	   READNEW = -1
+	   BRIEF = -1
+	END IF
+  	IF (DEFAULT.OR.NODEFAULT) THEN
+	   IF (NODEFAULT.AND..NOT.SUB) THEN
+	      IF (NOTIFY.NE.-1) CALL SET_NEWS_FLAG(IER,0,-1,-1)
+	      IF (READNEW.NE.-1.OR.BRIEF.NE.-1)
+     &		CALL SET_NEWS_FLAG(IER,-1,0,0)
+	   ELSE
+	      CALL SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+	   END IF
+           IF (.NOT.IER) THEN
+              CALL CLOSE_BULLNEWS
+              CALL CLOSE_BULLINF
+              RETURN
+           END IF
+	   IF (IER1.EQ.0) THEN
+	      REWRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+	   ELSE
+	      WRITE (9,IOSTAT=IER) '*DEFAULT    ',INF_REC
+	   END IF
+	END IF
+	IF ((ALL.OR.(SUB.AND.INCMD(:3).NE.'SET')).AND.IER.EQ.0) THEN
+	   CALL OPEN_BULLUSER_SHARED
+	   CALL READ_USER_FILE_HEADER(IER)
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0)
+	      IF (TEMP_USER(:1).NE.'*'.AND.TEMP_USER(:1).NE.':') THEN
+	         LU = TRIM(TEMP_USER)
+	         TEMP_USER(LU:LU) = CHAR(128.OR.ICHAR(TEMP_USER(LU:LU)))
+	         IF (LU.GT.1) THEN
+	            TEMP_USER(LU-1:LU-1) =
+     &			CHAR(128.OR.ICHAR(TEMP_USER(LU-1:LU-1)))
+	         ELSE
+	            TEMP_USER(2:2) = CHAR(128.OR.ICHAR(TEMP_USER(2:2)))
+	         END IF
+	         DO WHILE (REC_LOCK(IER1))
+                    READ (9,KEY=TEMP_USER,IOSTAT=IER1) TEMP_USER,INF_REC
+	         END DO
+       	         IF (IER1.NE.0) THEN
+	            DO I=1,FOLDER_MAX
+	               INF_REC(1,I) = 0
+	               INF_REC(2,I) = 0
+	            END DO
+	         END IF
+	         CALL SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+		 IF (IER1.EQ.0) THEN
+		    REWRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+		 ELSE
+	            WRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+		 END IF
+	      END IF
+	      CALL READ_USER_FILE(IER)
+ 	   END DO
+	   CALL CLOSE_BULLUSER
+	END IF
+
+	CALL CLOSE_BULLNEWS
+	CALL CLOSE_BULLINF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE READ_INF_REC
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CALL OPEN_BULLINF_SHARED
+        DO WHILE (REC_LOCK(IER1))
+           READ (9,KEY='*PERM',IOSTAT=IER1) TEMP_USER,INF_REC
+	END DO
+	IF (IER1.NE.0) THEN
+           DO I=1,FOLDER_MAX
+              INF_REC(1,I) = 0
+              INF_REC(2,I) = 0
+           END DO
+        END IF
+	CALL CLOSE_BULLINF
+
+	RETURN
+
+	ENTRY SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+
+	I = 1
+	DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER_NUMBER.AND.
+     &		INF_REC2(1,I).NE.0.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	IF (I.GT.FOLDER_MAX-1.AND.TEMP_USER(:1).EQ.'*') THEN
+	   WRITE (6,'('' ERROR: You have '',
+     &		    '' reached the news folder limit of '',I,''.'')')
+     &		    FOLDER_MAX-1
+	   IER = 0
+	   RETURN
+	END IF
+
+	IF (INF_REC2(1,I).EQ.NEWS_FOLDER_NUMBER) THEN
+	   IF (NOTIFY.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),13)
+	   IF (NOTIFY.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),13)
+	   IF (READNEW.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),14)
+	   IF (READNEW.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),14)
+	   IF (BRIEF.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),15)
+	   IF (BRIEF.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),15)
+  	   IF (NOTIFY+READNEW+BRIEF.EQ.-3) THEN
+	      DO J=I,FOLDER_MAX-2
+	         CALL COPY2(INF_REC(1,J),INF_REC(1,J+1))
+              END DO
+	   END IF
+	   IER = 1
+	   RETURN
+	END IF
+
+	IF (NOTIFY+READNEW+BRIEF.EQ.-3) RETURN
+
+	DO J=I,1,-1
+	   IF (J.GT.1) THEN
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(
+     &	         ZEXT(INF_REC2(1,J-1)),IER)
+	      IF (FOLDER_DESCRIP.LT.FOLDER1_DESCRIP) THEN
+	         CALL COPY2(INF_REC(1,J),INF_REC(1,J-1))
+	      END IF
+	   END IF
+	   IF (FOLDER_DESCRIP.GT.FOLDER1_DESCRIP.OR.J.EQ.1) THEN
+	      INF_REC2(1,J) = NEWS_FOLDER_NUMBER
+	      IF (F_START.LE.F_NBULL) THEN
+		 INF_REC2(2,J) = MIN(8191,F_NBULL-(F_START-1))
+		 INF_REC(2,J) = F_START - 1
+	      ELSE
+		 INF_REC2(2,J) = 0
+		 INF_REC(2,J) = F_NBULL
+	      END IF
+	      IF (NOTIFY.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),13)
+	      IF (NOTIFY.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),13)
+	      IF (READNEW.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),14)
+	      IF (READNEW.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),14)
+	      IF (BRIEF.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),15)
+	      IF (BRIEF.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),15)
+	      IER = 1
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+	END
diff --git a/decus/vmslt00a/bulletin/bullfiles.inc b/decus/vmslt00a/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..0df9866c997645bd450919b1e2f85513c064a695
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullfiles.inc
@@ -0,0 +1,39 @@
+C
+C  FOLDER_DIRECTORY IS THE DIRECTORY THAT FILES FOR FOLDERS THAT
+C  ARE CREATED ARE KEPT IN.  IF YOU WISH TO PREVENT FOLDER CREATION,
+C  YOU SHOULD MODIFY BULLCOM.CLD TO MAKE THE CREATE COMMAND A PRIVILEGED
+C  COMMAND (OR SIMPLY REMOVE THE LINES WHICH DEFINE THE CREATE COMMAND).
+C
+C  BBOARD_DIRECTORY IS THE SCRATCH AREA USED BY BBOARD WHEN EXTRACTING
+C  MAIL.  IF IT IS UNDEFINED, BBOARD WILL NOT BE ABLE TO BE USED.
+C  NOTE THAT EITHER THE BBOARD ACCOUNTS MUST HAVE ACCESS TO THIS DIRECTORY,
+C  OR THE BBOARD ACCOUNTS MUST BE GIVEN SYSPRV PRIVILEGES TO BE ABLE
+C  TO WRITE INTO THIS DIRECTORY.  ALSO, FOR BBOARD TO WORK, MAKE SURE
+C  THAT THE SUBPROCESS LIMIT FOR USERS IS AT LEAST 2.  YOU WILL ALSO HAVE
+C  TO INCREASE THE FOLLOWING SYSTEM PARAMETERS WHICH AFFECT DETACHED PROCESES:
+C  PQL_DPGFLQUOTA = 15000, PQL_DWSQUOTA = 500, & PQL_DFILLM = 30.
+C  (NOTE: ACCESS CAN BE GIVEN TO THE DIRECTORY FOR THE BBOARD ACCOUNTS USING
+C  ACLS, I.E. " SET ACL/ACL=(ID=bboard,ACCESS=R+W)/OBJ=FILE directory.DIR")
+C
+	COMMON /FILES/ BULLFOLDER_FILE,FOLDER_DIRECTORY,BBOARD_DIRECTORY
+	COMMON /FILES/ BULLUSER_FILE,BULLINF_FILE,NEWS_DIRECTORY
+	COMMON /FILES/ BULLNEWS_FILE
+	CHARACTER*80 FOLDER_DIRECTORY /'BULL_DIR:'/
+	CHARACTER*80 BBOARD_DIRECTORY /'BULL_DIR:'/
+C
+C  NOTE: THE FOLLOWING FILE ARE STORED IN THE FOLDER_DIRECTORY BY DEFAULT.
+C  YOU CAN CHANGE THIS BY ADDING A DIRECTORY NAME TO THE FILE NAME.
+C
+	CHARACTER*80 BULLUSER_FILE /'BULLUSER.DAT'/	! Stores user login time
+							! & folder flag settings
+	CHARACTER*80 BULLFOLDER_FILE /'BULLFOLDER.DAT'/	! Stores folder data
+	CHARACTER*80 BULLINF_FILE /'BULLINF.DAT'/	! Stores times of last
+							! read messages of users
+	CHARACTER*80 BULLNEWS_FILE /'BULLNEWS.DAT'/	! Stores news group data
+C
+C  THE FOLLOWING IS THE DIRECTORY THAT IS USED TO STORE LOCAL NEWS GROUPS,
+C  I.E. NEWS GROUPS THAT ARE COPIED FROM THE NEWS SERVER AND SAVED LOCALLY.
+C  BULLETIN WILL CREATE SUBDIRECTORIES IN THIS DIRECTORY AND THE FILES WILL
+C  BE STORED IN THOSE SUBDIRECTORIES.
+C
+	CHARACTER*80 NEWS_DIRECTORY /'BULL_DIR:'/
diff --git a/decus/vmslt00a/bulletin/bullfolder.inc b/decus/vmslt00a/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..b3d94c80a06497cda925568659d1cc32f0fe7e7e
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullfolder.inc
@@ -0,0 +1,84 @@
+!
+!  The following 2 parameters can be modified if desired before compilation.
+!
+	PARAMETER BBEXPIRE_LIMIT = 30	! Maxmimum time limit in days that
+					! BBOARDS can be set to.
+	PARAMETER BBOARD_UPDATE = 15	! Number of minutes between checks
+					! for new BBOARD mail. (Note: Check
+					! only occurs via BULLETIN/LOGIN.
+					! Check is forced via BULLETIN/BBOARD).
+					! NOT APPLICABLE IF BULLCP IS RUNNING.
+	PARAMETER ADDID = .TRUE.	! Allows users who are not in the
+					! rights data base to be added
+					! according to uic number.
+
+	PARAMETER FOLDER_FMT = '(A44,A4,A8,A12,A80,A12,3A4,A8,10A4)'
+	PARAMETER FOLDER_RECORD = 220	! Must be multiple of 4
+
+	COMMON /BULL_FOLDER/ FOLDER,FOLDER_NUMBER,FOLDER_CREATED_DATE,
+     &		FOLDER_OWNER,
+     &		FOLDER_DESCRIP,FOLDER_BBOARD,FOLDER_BBEXPIRE,
+     &		USERB,GROUPB,ACCOUNTB,
+     &		F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,F_EXPIRE_LIMIT,
+     &		F_NEWEST_NOSYS_BTIM,F_START,F_COUNT,F_LAST,
+     &		FOLDER_FILE,FOLDER_SET,FOLDER_NAME
+	INTEGER F_NEWEST_BTIM(2)
+	INTEGER F_NEWEST_NOSYS_BTIM(2)
+	LOGICAL FOLDER_SET
+	DATA FOLDER_SET /.FALSE./, FOLDER/'GENERAL'/
+	CHARACTER FOLDER_OWNER*12,FOLDER*44,ACCOUNTB*8,FOLDER_NAME*80
+	CHARACTER FOLDER_FILE*80,FOLDER_DESCRIP*80,FOLDER_BBOARD*12
+	CHARACTER FOLDER_CREATED_DATE*8
+
+	CHARACTER*(FOLDER_RECORD) FOLDER_COM
+	EQUIVALENCE (FOLDER,FOLDER_COM)
+
+	COMMON /BULL_FOLDER1/ FOLDER1,FOLDER1_NUMBER,FOLDER1_CREATED_DATE,
+     &		FOLDER1_OWNER,
+     &		FOLDER1_DESCRIP,FOLDER1_BBOARD,FOLDER1_BBEXPIRE,
+     &		USERB1,GROUPB1,ACCOUNTB1,
+     &		F1_NBULL,F1_NEWEST_BTIM,FOLDER1_FLAG,F1_EXPIRE_LIMIT,
+     &		F1_NEWEST_NOSYS_BTIM,F1_START,F1_COUNT,F1_LAST,
+     &		FOLDER1_FILE,FOLDER1_SET,FOLDER1_NAME
+	CHARACTER FOLDER1_OWNER*12,FOLDER1*44,ACCOUNTB1*8,FOLDER1_NAME*80
+	CHARACTER FOLDER1_FILE*80,FOLDER1_DESCRIP*80,FOLDER1_BBOARD*12
+	CHARACTER FOLDER1_CREATED_DATE*8
+	INTEGER F1_NEWEST_BTIM(2)
+	INTEGER F1_NEWEST_NOSYS_BTIM(2)
+
+	CHARACTER*(FOLDER_RECORD) FOLDER1_COM
+	EQUIVALENCE (FOLDER1,FOLDER1_COM)
+
+	PARAMETER NEWS_FOLDER_FMT = '(A44,A4,2A8,A36,11A4)'
+	PARAMETER NEWS_FOLDER_RECORD = 144	! Must be multiple of 4
+
+	COMMON /NEWS_FOLDER/ NEWS_FOLDER,NEWS_FOLDER_NUMBER,
+     &		NEWS_F_CREATED_DATE,NEWS_F_EXPIRED_DATE,
+     &		NEWS_FOLDER_DESCRIP,NEWS_F_START,NEWS_F_COUNT,
+     &		NEWS_F_NBULL,NEWS_F_NEWEST_BTIM,NEWS_F_LAST,
+     &		NEWS_F_FLAG,NEWS_F_EXPIRE,NEWS_F_FIRST,
+     &		NEWS_F_EXPIRE_LIMIT,NEWS_F_END 
+	INTEGER NEWS_F_NEWEST_BTIM(2)
+	CHARACTER NEWS_FOLDER*44
+	CHARACTER NEWS_FOLDER_DESCRIP*36
+	CHARACTER*8 NEWS_F_CREATED_DATE,NEWS_F_EXPIRED_DATE
+
+	CHARACTER*(NEWS_FOLDER_RECORD) NEWS_FOLDER_COM
+	EQUIVALENCE (NEWS_FOLDER,NEWS_FOLDER_COM)
+
+        COMMON /NEWS_FOLDER_DEFAULT/ NEWS_FLAG_DEFAULT,
+     &	        NEWS_EXPIRE_DEFAULT,NEWS_EXPIRE_LIMIT_DEFAULT
+
+	COMMON /NEWS_FOLDER1/ NEWS_FOLDER1,NEWS_FOLDER1_NUMBER,
+     &		NEWS_F1_CREATED_DATE,NEWS_F1_EXPIRED_DATE,
+     &		NEWS_FOLDER1_DESCRIP,NEWS_F1_START,NEWS_F1_COUNT,
+     &		NEWS_F1_NBULL,NEWS_F1_NEWEST_BTIM,NEWS_F1_LAST,
+     &		NEWS_F1_FLAG,NEWS_F1_EXPIRE,NEWS_F1_FIRST,
+     &	        NEWS_F1_EXPIRE_LIMIT,NEWS_F1_END
+	INTEGER NEWS_F1_NEWEST_BTIM(2)
+	CHARACTER NEWS_FOLDER1*44
+	CHARACTER NEWS_FOLDER1_DESCRIP*36
+	CHARACTER*8 NEWS_F1_CREATED_DATE,NEWS_F1_EXPIRED_DATE
+
+	CHARACTER*(NEWS_FOLDER_RECORD) NEWS_FOLDER1_COM
+	EQUIVALENCE (NEWS_FOLDER1,NEWS_FOLDER1_COM)
diff --git a/decus/vmslt00a/bulletin/bullmain.cld b/decus/vmslt00a/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..bb3a4b5c7a988fd11c5c67a8b99fe2792c2177b2
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullmain.cld
@@ -0,0 +1,34 @@
+	MODULE BULLETIN_MAINCOMMANDS
+	DEFINE VERB BULLETIN
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER ALL
+		QUALIFIER BBOARD
+		QUALIFIER BULLCP
+		QUALIFIER CLEANUP, LABEL=CLEANUP, VALUE(REQUIRED)
+		QUALIFIER EDIT
+		QUALIFIER KEYPAD, DEFAULT
+		QUALIFIER LIBRARY, VALUE(REQUIRED)
+		QUALIFIER LOGIN
+		QUALIFIER MARKED
+		QUALIFIER PAGE, DEFAULT
+		QUALIFIER PGFLQUOTA, VALUE(TYPE=$NUMBER, REQUIRED)
+		QUALIFIER READNEW
+		QUALIFIER REVERSE
+!
+! The following line causes a line to be outputted separating system notices.
+! The line consists of a line of all "-"s, i.e.:
+!--------------------------------------------------------------------------
+! If you want a different character to be used, simply put in the desired one
+! in the following line.  If you want to disable the feature, remove the
+! DEFAULT at the end of the line.  (Don't remove the whole line!)
+!
+		QUALIFIER SEEN
+		QUALIFIER SEPARATE, VALUE(DEFAULT="-"), DEFAULT
+		QUALIFIER STARTUP
+		QUALIFIER STOP
+		QUALIFIER SYSTEM, VALUE(TYPE=$NUMBER, DEFAULT="7")
+		QUALIFIER UNSEEN
+		QUALIFIER UNMARKED
+		QUALIFIER WIDTH, VALUE(TYPE=$NUMBER, REQUIRED)
+		QUALIFIER WSEXTENT, VALUE(TYPE=$NUMBER, REQUIRED)
+		DISALLOW (WSEXTENT OR PGFLQUOTA) AND NOT STARTUP
diff --git a/decus/vmslt00a/bulletin/bullnews.inc b/decus/vmslt00a/bulletin/bullnews.inc
new file mode 100755
index 0000000000000000000000000000000000000000..fcbc81f4e3370155961774efc113178be317b39f
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullnews.inc
@@ -0,0 +1,7 @@
+	COMMON /NEWS_DEFAULTS/ ORGANIZATION,MAILER
+
+	CHARACTER*132 ORGANIZATION
+	DATA ORGANIZATION /'MIT PLASMA FUSION CENTER'/
+
+	CHARACTER*12 MAILER
+	DATA MAILER /'IN%'/
diff --git a/decus/vmslt00a/bulletin/bullstart.com b/decus/vmslt00a/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..ed1779cc0191d92a6e378bbb27c5c82fd163428d
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bullstart.com
@@ -0,0 +1,6 @@
+$ RUN SYS$SYSTEM:INSTALL
+BULL_DIR:BULLETIN/SHAR/OPEN/HEAD/-
+PRIV=(OPER,SYSPRV,CMKRNL,WORLD,DETACH,PRMMBX,SYSNAM)
+/EXIT
+$ BULL*ETIN :== $BULL_DIR:BULLETIN
+$ BULLETIN/STARTUP
diff --git a/decus/vmslt00a/bulletin/bulluser.inc b/decus/vmslt00a/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..5760e9235c2b5c12dbb4e64c63708fce310c3073
--- /dev/null
+++ b/decus/vmslt00a/bulletin/bulluser.inc
@@ -0,0 +1,53 @@
+!
+! The parameter FOLDER_MAX should be changed to increase the maximum number
+! of folders available.  Due to storage via longwords, the maximum number
+! available is always a multiple of 32.  Thus, it will probably make sense
+! to specify a multiple of 32 for FOLDER_MAX, as that it what really will be
+! the capacity.  Note that the default general folder counts as a folder also,
+! so that if you specify 64, you will be able to create 63 folders on your own.
+!
+	PARAMETER FOLDER_MAX = 96
+	PARAMETER FLONG = (FOLDER_MAX + 31)/ 32
+
+	PARAMETER USER_RECORD_LENGTH = 28 + FLONG*16
+	PARAMETER USER_FMT = '(A12,<4+FLONG*4>A4)'
+	PARAMETER USER_HEADER_KEY = '            '
+
+	COMMON /HEADER_INFO/ TEMP_USER,BBOARD_BTIM,NEWEST_BTIM,USERPRIV
+	COMMON /HEADER_INFO/ SET_FLAG_DEF,BRIEF_FLAG_DEF
+	COMMON /HEADER_INFO/ NOTIFY_FLAG_DEF
+	CHARACTER TEMP_USER*12
+	DIMENSION BBOARD_BTIM(2),NEWEST_BTIM(2),USERPRIV(FLONG)
+	DIMENSION SET_FLAG_DEF(FLONG),BRIEF_FLAG_DEF(FLONG)
+	DIMENSION NOTIFY_FLAG_DEF(FLONG)
+
+	COMMON /BULL_USER/ USERNAME,LOGIN_BTIM,READ_BTIM,
+     &		NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	CHARACTER*12 USERNAME
+	DIMENSION LOGIN_BTIM(2),READ_BTIM(2)
+	DIMENSION NEW_FLAG(FLONG)   ! Used to indicate new message in folder
+				    ! Now NEW_FLAG(2) contains SET GENERIC days
+	DIMENSION SET_FLAG(FLONG)   ! Bit set indicates READNEW set for folder
+	DIMENSION BRIEF_FLAG(FLONG) ! Bit set indicates READNEW/BRIEF set
+	DIMENSION NOTIFY_FLAG(FLONG)! Bit set indicates to broadcast
+				    ! notification when new bulletin is added.
+
+	CHARACTER*(USER_RECORD_LENGTH) USER_ENTRY,USER_HEADER
+	EQUIVALENCE (USER_ENTRY,USERNAME)
+	EQUIVALENCE (USER_HEADER,TEMP_USER)
+
+	COMMON /FOLDER_TIMES/ LAST_READ_BTIM(2,0:FOLDER_MAX)
+	   ! Must start with 0 to store info for folder specified with ::
+	COMMON /SYS_FOLDER_TIMES/ LAST_SYS_BTIM(2,FOLDER_MAX)
+	   ! Last read times for each folder as stored in BULL_DIR:BULLINF.DAT
+	COMMON /NEWS_TIMES/ LAST_NEWS_READ(2,FOLDER_MAX)
+	INTEGER*2 LAST_NEWS_READ2(4,FOLDER_MAX)
+	EQUIVALENCE (LAST_NEWS_READ2(1,1),LAST_NEWS_READ(1,1))
+	   ! Last read times for each folder as stored in BULL_DIR:BULLINF.DAT
+
+	COMMON /INF_REC/ INF_REC(2,FOLDER_MAX)
+	INTEGER*2 INF_REC2(4,FOLDER_MAX)
+	EQUIVALENCE (INF_REC2(1,1), INF_REC(1,1))
+
+	COMMON /NEW_MESSAGES/ NEW_MSG
+	DIMENSION NEW_MSG(FLONG)   ! Flag showing new messages detected
diff --git a/decus/vmslt00a/bulletin/changes.txt b/decus/vmslt00a/bulletin/changes.txt
new file mode 100755
index 0000000000000000000000000000000000000000..e231fb35ee797aab0601c0e4113b2bb6fbf9ac56
--- /dev/null
+++ b/decus/vmslt00a/bulletin/changes.txt
@@ -0,0 +1,692 @@
+V2.5
+If a message gets rejected from a news server that was posted via a folder
+that has a news group associated with it, the error message gets sent to the
+local postmaster, and the message continues to attempt to be posted until it
+is either delivered, or the postmaster kills it.  10/20/98
+
+Fixed bug which caused the RESET command to wipe out SET NOTIFY on a new
+group.  10/6/98
+
+Changed behavior of threads and excludes.  Only excludes based on FROM will
+take precedence over THREADs.  10/1/98
+
+Fixed 2 very old bugs.  One which would cause one of the databases to be 
+stuck opened preventing anyone else from using BULLETIN, the other which
+caused READNEW behavior when logging in for folders which did not have that 
+feature enabled.  9/20/98
+
+V2.4
+Adding the ability to change one's personal name used in postings to news
+groups and mail message by defining the logical name BULL_PERSONAL_NAME.
+7/22/98
+
+Added the SET GATEWAY command to change the how the subject lines looks in
+messages which are sent to an email address associated with a folder.  2/25/98
+
+Many bugs were fixed, mainly with respect to the news-email-folder gateway.
+
+V2.3
+
+Added the ability to create a folder that can post and read to a news group,
+and can send and read messages via email.  See NEWS_TO_FOLDER.TXT for more
+info.  4/18/97
+
+Added the ability for BULLETIN to see news groups from secondary news groups
+(see NEWS.TXT).  4/18/97
+
+V 2.25
+
+Changes to make it easier to click on news group name to select them:  You can
+enter a news group name at the prompt and it will select it (without typing
+SELECT).  News groups displayed without period at end when BULLETIN lists the
+ones that have new messages.  NEWS/SUBS has space between * and news group
+when denoting which ones have new messages.  3/21/96
+
+V 2.24
+
+When replying to a message in a news group that has been crossposted, give the
+user  the  option  of  just  posting  the reply to the news group in which the
+message is being read rather than  all  the  news  groups  in  the  crosspost.
+11/20/95
+
+Messages added to folders and stored news groups are now marked as being  read
+so that the person does not see them when doing a READ/NEW.  11/20/95
+
+Removed INCLUDE command and replaced it with the THREAD command.    This
+allows  you  to  save  and  easily  read new messages in threads via the
+READ/THREADS command.  11/13/95
+
+V 2.23
+
+Update newest read message when switching folders.  Previously this was done
+only when you exited BULLETIN, which would cause problems if you ran BULLETIN
+simultaneously from two different logins.  9/12/95
+
+Added /LIMIT to EXCLUDE and also the SET EXLIMIT command.   These  allow
+excludes to be specified so that they expire after a specified amount of
+days.  The SHOW EXCLUDE now will show the last time a message was found 
+that matched the exclude.  8/16/95
+
+Added /GROUP qualifier to DIRECTORY command to allow  specifying  groups
+to search using wild cards names.  8/3/95
+
+Added /GROUP qualifier to SEARCH command to allow specifying  groups  to
+search using wild cards names.  6/20/95
+
+V 2.22
+
+Added SHOW EXCLUDE and INCLUDE commands.  5/17/95
+
+Fixed bugs relating to messages with an expiration year past 1999.  5/17/95
+
+Fixed EXCLUDE/FROM as it did not work.   Also  fixed  EXCLUDE/DISABLE/ALL  and
+INCLUDE/DISABLE/ALL, as in some cases they would not work.3/31/95 
+
+V 2.21
+
+Modified the file format for stored news group to reduce disk space usage.
+11/29/94
+
+Added SET LIBRARY command and also /LIBRARY qualifier on the command line to
+allow switching between different directories which contain different sets of
+folders.  11/29/94
+
+Added /HEADER to POST when posting to news groups to allow adding headers to
+the message.  11/9/94
+
+Added /CANCEL to PRINT command which cancels previous print commands.
+10/28/94
+
+V 2.20
+
+Added /FOLLOWUP to the POST command.  10/12/94
+
+The FILE command no longer requires a file name, but will create a file
+name from the folder's name.  5/25/94
+
+Allow logical names to be specified in POST/GROUP.  5/12/94
+
+Added SET FILE_DIRECTORY command.  5/12/94
+
+Added /PERMANENT and /DEFAULT qualifiers to NEWS command.  4/28/94
+
+Added SET SUBSCRIBE command to allow setting default or permanent news groups. 
+4/26/94
+
+Added code to mail rejected posting for a stored news group to poster.  4/6/94
+
+Optimized newsgroup list upgrade to reduce  disk  I/O  which  greatly  reduces
+elapsed time for slow or fragmented disks.  4/5/94
+
+Modified /EDIT so EDT error no longer shows "no file found" message.  4/5/94
+
+Added SET NAME command to copy settings, used if username is changed.  3/28/94
+
+Modified SEARCH command to avoid updating new message counter (in order to be
+able to follow a thread and still use READ/NEW later).  3/26/94
+
+Added /INDENT=string to allow different indentation string.  3/12/94
+
+Added ability to allow BULLCP to gateway for NEWS access via TCP (for MULTINET
+only).  2/24/94
+
+Fix FROM header for news groups messages that have an address which continues
+on a 2nd line.  12/17/93
+
+V 2.19
+
+Add /MATCH qualifier to SEARCH command, and allow more than 1 string to be
+specified.  12/2/93
+
+Fixed the qualifer /CC when posting or resonding to messages.  It was supposed
+to be able to send to more than one user, but actually was sending to only the
+first user specified.  7/17/93
+
+Fixed alpha related problems.  7/16/93
+
+Fixed problem with responding to addresses of form: name <address>.  7/2/93
+
+Fixed shutdown bugs.  6/6/93
+
+Fixed /PRINT and /EXTRACT in DIRECTORY when used with a remote news group.
+5/29/93
+
+System messages which have longer lines than the terminal page width will have
+their text left justified rather than simply wrapped.  5/28/93
+
+Added SET [NO]EXCLUDE command to be  able  to  ignore  any  excludes  or
+includes that have been specified for that folder.  5/20/93
+
+V 2.18
+
+Added /FULL to EXCLUDE  and  INCLUDE  command  to  make  it  affect  all
+commands, such as directory listings.  5/13/93
+
+Fixed bug which displayed wrong foldername for notification broadcasts for
+messages added to bboard folders with digest set.  5/13/93
+
+Fixed bug which caused FOR003.DAT files to appear in DECNET directory due to
+BBOARD folder which has digest set.  5/10/93
+
+Fixed problem with inserting correct time when posting to news group.  5/5/93
+
+Fixed problem with BULL_DIR_LIST usage.  5/5/93
+
+Fixed shutdown problems.  5/3/93
+
+Fixed new executable message.  5/3/93
+
+Fixed bugs which caused FOR00x.DAT files to appear in DECNET directory during
+access from remote nodes.  4/29/93
+
+V 2.17
+
+Modified to work for ALPHA cpus.  4/5/93
+
+Speeded up DIRECTORY listing.  3/18/93
+
+Fixed FORWARD command from truncating subject lengths > 64.  3/18/93
+
+V 2.16
+
+Add code which causes nodename of remote folders to automatically be updated
+when the bulletin data files of the node containing the remote folders are
+moved to a different node.  3/12/93
+
+Fix incorrect display of NEWS/SUBSCRIBE/COUNT.  3/6/93
+
+In batch mode, paging is now automatically turned off and page width set to 80.
+3/5/93
+
+Fixed problem with shutdown messages not being deleted.  3/4/93
+
+V 2.15
+
+Code that converts data files if FOLDER_MAX is increased did not work.  2/27/93
+
+NEWS/SUBS now shows last read message.  INDEX now shows listing similar to
+DIR/FOLDER and NEWS. 2/27/93
+
+A user can make /HEADER be made the default for a folder or news group by adding
+a line to the user's customization file.  (See HELP custom) 2/21/93
+
+Personal names which are set in VMS MAIL are now automatically added to the from
+address when posting to news groups.  2/15/93
+
+Fixed bug which caused only partial storage of specified local news groups.
+2/5/93
+
+Fixed bug that caused privilege error and crash to occur after a non-privileged
+user posted a message to a folder which had an associated mailing list.  2/5/93
+
+V 2.14
+
+Added SET ANONYMOUS command so that all messages added to a folder will have
+the username ANONYMOUS rather than the actual username.  2/1/93
+
+Added /EXTRACT qualifie to DIRECTORY command.  1/31/93
+
+Added notification of new executable and possible new features.  1/26/93
+
+Dump log files are now created with acl for folder owner to be able to delete
+it.  1/26/93
+
+V 2.13
+
+Fixed bug in BBOARD code that corrupts file length.  1/15/93
+
+Fixed notification messages that showed wrong folder name.  1/15/93
+
+Added /[NO]HEADER and /ROTATE to NEXT (help said they were there, but they
+weren't).  1/15/93
+
+Added RESET command.  1/9/93
+
+Fixed bug in posting to stored news group by non-privileged users.  12/28/92
+
+V 2.12
+
+Fixed SET ACCESS /ALL which broke due to changes in V 2.11.  12/28/92
+
+Fixed problem with reply posting to stored news group not posting to proper
+group.  12/28/92
+
+Added code to allow setting access to news group or class of news groups.
+Added /PRIVATE switch to SET NEWS.  Added /CLASS to SET ACCESS.  12/26/92
+
+Fixed bug in code that does copying from news group to folder.  12/26/92
+
+Added INCLUDE and EXCLUDE commands which allow avoiding reading messages based
+on subject and address headers.  12/15/92
+
+Fixed bug which caused folder corruption.  12/15/92
+
+V 2.11
+
+Added SET NEWS command.  Used for setting a news group or a class of news
+groups to be stored on disk for quicker access by users (rather than being 
+read by users directly from the server).  Can also disable access to a group. 
+Users can set NOTIFY on stored groups.  11/5/92
+                                       
+NEWS command now by default shows only groups which are active.  Can show all
+groups with /ALL command.  /STORED and /COUNT are new qualifiers.  11/5/92
+
+Stored news groups are stored with data compression.  Normal folders can also be
+stored that way if set with the SET COMPRESS command.  11/5/92
+
+INDEX command modified to make it more useful.  /NEW is now the default, and now
+only shows folders or groups that have new messages.  /SET added to show only
+folders which have READNEW, SHOWNEW, or BRIEF set, and /SET is the default.
+11/5/92
+
+Fixed bug with BROADCAST routines which could cause BULLCP to go into MWAST
+state.  11/5/92
+
+Modified code which adds BBOARD messages to speed it up when multiple messages
+are being added.  11/5/92
+                                                 
+Folder names can now be up to 44 letters long.  11/5/92
+
+BULL_BBOARD_UPDATE and BULL_NEWS_UPDATE are now continuously translated by
+BULLCP so that they can be changed dynamically.  11/5/92
+
+BULLCP now is created with reasonable working quotas rather than PQL_ defaults
+which are usually way too low.  11/5/92
+
+Changed all variables to be long word multiples in order to be more ALPHA
+compliant (and maybe faster because of it?).  11/5/92
+
+/ROTATE added for read commands to allow reading messages encoded in ROT-13
+coding.  This is used by some news groups to display messages which could be
+taken as being offensive (i.e. rec.humor.funny).  11/5/92
+
+Fixed many minor bugs that no one mentioned, so I won't either.  11/5/92
+
+Fixed ADD/BROADCAST/EDIT not working with TPU.  8/13/92
+
+V 2.10
+
+Allow non-digest messages to be added to a folder which has DIGEST set.  8/6/92
+
+Added ADD_ONLY attribute.  If a mailing address is present, when messages are
+added to a folder, they will also be mailed to the address.  Users are
+prevented from using the POST command.  Instead, the ADD command will be used
+if the POST command is entered.  One use for this is a local board which is
+also distributed to non-local users.  8/1/92
+
+Added POST_ONLY attribute  This causes the ADD command to mail messages to the
+mailing address if it is present, rather than add it to the folder.  8/1/92
+
+Fixed several shutdown bugs.  7/23/92
+
+Fixed PMDF broken by V2.09.  6/16/92
+
+Added system logical name BULL_CUSTOM.  It is equated to a hex number string.  
+Bit 0 set = need privileges to create folder, 1 set = captive account can
+write files, 2 set = captive account can use editor.  5/25/92
+
+V 2.09
+
+Allow having more than one database by redefining BULL_DIR.  However, only 
+directories that are defined in the list of equivalence names pointed to by
+the system logical name BULL_DIR_LIST are allowed.  See AAREADME.TXT
+for more info.  5/10/92
+
+GENERAL folder can now be renamed or modified (not deleted).  4/22/92
+
+/FROM, /NOREPLIES, & /NEGATED added to SEARCH and DIRECTORY commands.  3/18/92
+
+Mail routines now use MAIL$ calls for outgoing mail for faster execution.  
+3/15/92
+
+Changing keypad definitions using initialization file now possible.  3/12/92
+
+Subscribed news groups are now listed in alphabetical order.  3/7/92
+
+V 2.08
+
+Fixed bug which caused missing news groups. See NEWS.TXT for info.  2/25/92
+
+Allow setting local protection on remote folders.  12/12/91
+
+Fixed bug with creation of folder files.  If they were deleted after the folder
+was created, the files that would be created by BULLETIN to replace them (when
+the folder is selected) would be created with the wrong protection.  12/12/91
+
+Fix problem with MULTINET V3.0 and DECNET/NEWS gateway feature.  BULLCP will
+hang without this fix if there is an attempt to read news via it.  12/9/91
+
+Fix bug that causes incorrect time on news postings after the first post. 
+Display time when reading news messages in local rather than GMT time.  12/8/91
+
+Add 30 second timeout for connecting to nameserver for news.  Can be increased
+up to 99 seconds via defining BULL_NEWS_TIMER.  12/3/91
+
+Allow list of numbers when specifying message numbers for PRINT and FILE
+commands.  11/27/91
+
+Fixed bugs in BBOARD code:  Messages with lines > 255 characters would not be
+included.  Subject line not correctly extracted if next line was simply a
+To:. (relink PMDF driver if using PMDF for patch to take affect).  11/27/91
+
+V 2.07
+
+NEWS listing now shows the status of the news group, i.e. active, inactive,
+moderated, or renamed.  10/23/91
+
+Fixed PRINT command so that if a print qualifier (i.e. /QUEUE) is specified,
+it will cause any pending print jobs to be printed if the qualifier for the
+pending jobs is different.  10/23/91
+
+Added /NOSIGNATURE qualifier for POST & RESPOND commands.  10/21/91
+
+Fixed error in POST & RESPOND command.  If a file was specified on the command
+line, and /EDIT was specified, the file would be sent even if the user quit out
+of the edit, rather than exitting (i.e. outputting a file).  10/21/91
+
+Fixed REPLY option in READNEW, as it was possible for users with only read
+access to a folder to be able to add REPLY messages.  10/10/91
+
+Add REPLY option to READNEW feature when reading messages.  Also, really fix
+the REPLY command, as mentioned in V2.06.  8/11/91
+
+V 2.06
+
+Added code to keep track of which messages have been read a per message basis. 
+Added SEEN & UNSEEN commands.  Added /SEEN, /UNSEEN, and /UNMARKED to
+DIRECTORY, INDEX, READ, and SELECT commands.  Modified directory listing to
+indicate which messages have been SEEN.  7/31/91 
+
+Added /NOW to PRINT command.  Messages no longer have to be printed one message
+at a time.  It now works identical to VMS MAIL.  7/31/91
+
+Added code to NEWS users when new groups have been created.  User will be
+alerted when selecting a news group that new groups are present, and will be
+instructed to type NEWS/NEWGROUP in order to see them.  7/31/91
+
+Added /PRINT to DIRECTORY command to allow printing of messages which are found
+by using the DIRECTORY command.  7/31/91
+
+Modified directory listing display so that the first and last message in the
+folder are now displayed at the top.  Fixed bug which truncated very large news
+group names.  7/31/91
+
+Added FIRST command to read first message found in folder.  7/31/91
+
+Modified REPLY command for folders associated with mailing lists, so that the
+reply message to the mailing list rather than adding a local message.  7/31/91
+
+Modified code to correctly store subject headers from BBOARD mail which are
+more than one line long.  Previously, the subject would be truncated.  6/18/91
+
+V 2.05
+
+The MARK code was modified to work with NEWS folders.  6/3/91
+
+Added /FOLDER=(folder,[...]) to the SEARCH command to allow searching more than
+one folder at a time.  6/13/91
+
+NEWS/SUBSCRIBED listing was fixed.  If the list could not fit on a single page,
+a folder was skipped when the next page was shown.  6/3/91
+
+INDEX was fixed.  If it was used with the qualifiers /NEW or /MARK, and the
+directory listing of a folder was displayed, and then RETURN is entered to 
+skip to the next folder, the directory display of the next folder would be
+incorrect.  6/3/91 
+
+Fixed broadcast bug.  If a message was added with /BROADCAST to a remote folder
+from a node in a cluster which was not the node that BULLCP was running on. 
+The broadcast would appear twice on the cluster.  5/24/91
+
+Added code to alert user if message too large to be fully broadcasted.  5/24/91
+
+Added code to avoid erroneous notifications of new messages for an empty NEWS
+group.  Unlike a similar fix in V2.03 which was due to a bug, this fix may not
+affect all sites, as it depends on the behavior of the server.  5/22/91 
+
+Fixed NEWS to FOLDER feed.  A recent change broke it.  5/22/91
+
+Added /EDIT qualifier for MAIL.  5/20/91
+
+Added /HEADER qualifier for LAST, BACK, and CURRENT commands.  5/19/91
+
+Added TWG (Wollongong) interface for NEWS.  5/18/91
+
+Fixed bug which truncated subject headers of messages created when using REPLY
+and RESPOND to messages which have long subject lines.  5/12/91
+
+V2.04
+
+Added ALWAYS attribute for folders.  Any SYSTEM messages in a folder in which
+ALWAYS has been set will be displayed every time a user logs in, rather than
+just once.  Also, non-SYSTEM messages will be displayed continuously (via
+whatever mode is set, i.e. READNEW, SHOWNEW, or BRIEF) until it is actually
+read.  4/29/91 
+
+Added capability of controlling the time between updates for BBOARD and NEWS in
+BULLCP by defining the logical names BULL_BBOARD_UPDATE or BULL_NEWS_UPDATE to
+the number of minutes of desired time in minutes. 4/27/91
+
+Added /GROUPS= qualifier to all commands which post to NEWS groups. 4/26/91
+
+Fixed bug which prevented SET SHOWNEW or READNEW from working with subscribed
+news group folders. 4/25/91
+
+V2.03
+
+Added /FOLDER to SHOW USER in order to show the latest message that a user
+has read in the specified folder.  Also added /SINCE and /START (the former
+for real folders, the latter for news groups).  4/11/91
+
+Fixed logic so that defining BULL_NEWS_ORGANIZATION will override the
+definition defined in BULLNEWS.INC.  4/10/91
+
+Fixed SEARCH command, as it broke in V2.02 when /EDIT was added to read
+message commands.  There is a missing QUALIFIER EDIT in BULLCOM.CLD for the
+SEARCH verb.  /EDIT now works with SEARCH.  4/9/91
+
+Fixed bug in BULLCP which prevented the DECNET/INTERNET NEWS gateway software
+from working with UCX.  4/9/91 
+
+Fixed bug caused by V2.00 which caused incorrect listing of message during
+BULL/LOGIN for remote folders.  4/3/91
+
+Fixed bugs which caused erroneous new message notifications for subscribed
+NEWS groups that were empty.	3/27/91
+
+V 2.02
+
+Include BBOARD support for MX (courtesy of goathunter@wkuvx1.bitnet).
+
+Changed BBOARD algorithm so that it is now possible to have only one real
+BBOARD account, and have all the others be VMS MAIL forwarding entries.
+See HELP SET BBOARD MORE_INFO for more info (it's been updated).
+
+Added hook to allow postings from BULLETIN to a LISTSERV mailing list to use
+the BBOARD account from it was subscribed to.  See HELP SET BBOARD LISTSERV.
+
+Fixed many bugs in POST, REPLY, and RESPOND.
+
+Fixed /ALL for COPY, PRINT, and EXTRACT when using NEWS groups.
+
+Included RMS optimizer procedure for indexed files to optimize BULLNEWS.DAT
+to speed up NEWS updates.  Can be used on other files (in particular
+BULLINF.DAT) in order to save space.
+
+Add /EDIT to BACK, NEXT, LAST, and when entering message number.
+
+Modify ADD/REPLY command to local (non-NEWS) folders so if there are new
+messages present, it doesn't reset the newest message count.  Previously,
+adding a message would reset the user's last read message date to that message
+in order to avoid notifying the user of new messages due to the user's own
+message. 
+
+Fixed code so that when reading new messages, and if READ/EDIT or DELETE/IMMED-
+IATE IS entered, a carriage return will read the next new message.  Previously
+the wrong message would be displayed.
+
+V 2.01
+
+Fixed many bugs associated with USENET NEWS reading feature.
+
+Added UCX interface for NEWS.
+
+Added signature file for POST and RESPOND messages.
+
+Added capability to specify file name for POST, REPLY, and RESPOND.
+
+Added the line "In a previous message, <message-owner> wrote:" to the
+beginning of a message when /EXTRACT is specified
+
+Added hook for network mail to run command procedure rather then using
+VMS MAIL.  BULL_MAILER can be defined to point to the procedure, and it
+is called with the username and subject as the parameters.
+
+V 2.00
+
+Added USENET NEWS reading feature.
+
+V 1.93
+
+Fixed bug which wouldn't allow a permanent message to be added by a
+non-privileged user in a remote folder (the folder had been setup to allow
+permanent messages from non-privileged users, of course). 
+
+Fixed bug which causes the DELETE command not to delete a SHUTDOWN message
+without the use of /IMMEDIATE.
+
+Fixed the algorithm which prevented duplicate notification of messages in
+remote folders on different nodes, as duplication was still possible.
+
+V 1.92
+
+Fixed bug which causes BULLCP to loop when trying to cleanup a folder which
+has more than 127 identifiers granted access to a folder.  Also correct
+SHOW FOLDER/FULL, which had a similar problem when trying to display the
+identifiers.
+
+Fix PMDF interface to recognize to recognize PMDF_PROTOCOL.
+
+V 1.91
+
+Disallow SPAWN command for CAPTIVE account.
+
+Fix MAIL command to correctly allow passing addresses with quotes, i.e.
+IN%"""MRL@NERUS.PFC.MIT.EDU""".
+
+V 1.90
+
+SET NOTIFY now works for remote folders.
+
+Avoid generating notification message due to SET NOTIFY flag if the message
+was broadcasted when added using ADD/BROADCAST.
+
+Bug in DIR/SINCE for remote folders fixed.  If no new messages were present,
+it would incorrectly show messages.
+
+Added /FF to EXTRACT command to seperate messages in the file with form feeds.
+
+Allow specifying CURRENT and LAST when specifying a range of messages for
+commands that accept a range, i.e. EXTRACT 1-CURRENT, CURRENT-LAST, etc.
+
+Open folder files with READONLY when not writing to them in order to avoid
+changing modification date, which results in unnecessary backups.
+
+Modify HELP so that it won't prompt for Subtopic is there is none.
+
+Prevent screen from being erased after exiting HELP.
+
+Fix bug which causes CREATE/NOTIFY to crash.
+
+SET NOTIFY/CLUSTER has been removed.  As of VMS V5.2, it is possible to obtain
+the list of users logged in to all nodes of a cluster, so this qualifier is no
+long necessary.  NOTE: You can delete all the BULL_DIR:*.NOTIFY files, as they
+are no longer used.
+
+BULLETIN now will use the editor specified by the SET EDITOR command within
+MAIL for editing messages.
+
+Typing BACK after typing a DIRECTORY command will now show the previous 
+DIRECTORY display entries rather than reading the previous message.
+
+Several bugs related to the MARK command were fixed.  Also the software has been
+optimized so that scanning for MARKed messages should take less time.
+
+/EXPIRATION added to DIRECTORY command to show expiration rather than creation
+date of messages.
+
+Any BULLETIN interactive command can be executed at DCL level by typing
+BULLETIN "command" or BULLETIN "command1;command2;etc.".
+
+The CHANGE command has been modified so a range of message can be specified,
+i.e. /NUMBER=1-10.  Also, the code incorrectly misinterpreted /TEXT as meaning
+to extract the old text message, whereas it should have meant that only the
+text was to be changed.  This prevented a user from specifying that only the
+text should be changed if that user didn't have editing enabled.  This has been
+fixed.  To eliminate confusing, the /TEXT qualifier on the ADD command has been
+removed (previously it was a synonym for /EXTRACT). 
+
+SHOW FOLDER/FULL display of access IDs was fixed to correctly display UICs.
+
+Removed security hole which occurs if you are using the old method of accessing
+a remote node via /NODES (it would have required looking a the sources to find,
+which one installer did and was worried about).  Because of this, if you use
+this old method (i.e. via BULLETIN.COM), the object BULLETIN must be installed
+in the NCP database pointing to the file BULLETIN.COM, i.e. the command
+"MCR NCP SET BULLETIN FILE directory:BULLETIN.COM NUMBER 0" must be executed
+during the system startup.
+
+Fixed bug in /LOGIN display when erasing page if terminal is hardcopy.  No
+page would be erased (of course), and the next line outputted would start where
+the previous line left off, rather than starting on a new line.
+
+Added BULLETIN/WIDTH=page_width for users who have BULLETIN/LOGIN in their
+login procedure before the terminal is known, and whose default page width is
+larger (i.e. 132) than what the terminals are (i.e. 80).
+
+Added BULLETIN/PGFLQUOTA and /WSEXTENT in order to set those quotas for the
+BULLCP process.
+
+Added ATTACH command.
+
+Modify SET STRIP so that it saves the date that the message was sent and
+leaves it at the to of the message.
+
+BULLETIN will search BBOARD message headers for a line that starts with
+"Expires:" or "X-Expires:", followed by a date (DD MMM YYYY or similar).  It if
+finds that line, it will use that date as the expiration date of the message. 
+
+Added /REPLY to SEARCH command.  Modified so that it's possible to abort out of
+a /SUBJECT or /REPLY search using CTRL-C (previous possible only if searching
+the text for a string.  Also, if you hit CTRL-C at the wrong time, BULLETIN
+would abort totally rather than just aborting the search). 
+
+Added /SEARCH= /SUBJ= and /REPLY to the DIRECTORY command.  Basically this is
+combining the DIRECTORY and SEARCH commands.
+
+Fixed design flaw which allowed the following to occur:  If a folder is a
+remote system folder, when BULLETIN/LOGIN was executed, the same messages might
+be displayed on both the local and remote nodes.  BULLETIN now will know that
+the user has seen the message on one node and will not display it if that user
+logs in on the other node.
+
+Optimized code which caused slow display of new messages when executing
+BULLETIN/LOGIN without /REVERSE for a remote folder.
+
+Added /PERMANENT to SET NOTIFY, SHOWNEW, BRIEF, and READNEW.  The affect is
+that users will not be allowed to change the setting.  The main intent here
+was to allow the removal ofthe permanent setting of SHOWNEW from the GENERAL
+folder.
+
+Fixed bug which would cause a SYSTEM message not to be shown if SET BRIEF was
+selected for that folder, and a non-SYSTEM message was also present.
+
+Added SET CONTINUOUS_BRIEF.  This causes the SET BRIEF setting to show that
+there are unread new messages every time BULLETIN/LOGIN is executed, rather
+than just the one time.  The BRIEF notification code has also been optimized
+so that it'll take less time to notify you of new messages.
+
+A major bug was fixed which was introduced in previous mods to speed up
+BULLETIN/LOGIN.  The effect is that no notifications will appear for certain
+folders via BULLETIN/LOGIN.  This would only happen if a folder was removed at
+some time.
diff --git a/decus/vmslt00a/bulletin/cmds.mai b/decus/vmslt00a/bulletin/cmds.mai
new file mode 100755
index 0000000000000000000000000000000000000000..804e43e75a08724e983452487e24fa87050266b6
--- /dev/null
+++ b/decus/vmslt00a/bulletin/cmds.mai
@@ -0,0 +1,22 @@
+The address for getting BULLETIN is BULLETIN@PFC.MIT.EDU.
+
+Valid commands are:
+	SEND ALL [SINCE time]	Sends all bulletin files.
+				If SINCE time specified, only files created
+				since that time will be sent.
+	SEND filename		Sends the specified file
+				(only one file per command).
+	DIR			Lists available files.
+	BUGS			Sends a list of the latest bug fixes.
+	HELP or INFO		Sends a brief description of BULLETIN.
+	SUBSCRIBE		Subscribes to mailing list for upgrade
+				notifications.
+	UNSUBSCRIBE		Unsubscribes from mailing list.
+
+Send those commands in either the text of the message, one command per line,
+or send a single command in the subject header.
+
+BULLETIN is also available via ANONYMOUS FTP from PFC.MIT.EDU, but the account
+is set at low priority, so I suggest using it during non-prime hours.
+
+								Mark
diff --git a/decus/vmslt00a/bulletin/copyright.txt b/decus/vmslt00a/bulletin/copyright.txt
new file mode 100755
index 0000000000000000000000000000000000000000..b6edd1b9bbf2a69adcdbbff41b17777c8b5a0989
--- /dev/null
+++ b/decus/vmslt00a/bulletin/copyright.txt
@@ -0,0 +1,29 @@
+"Bulletin" Z License
+
+This software is being provided to you, the LICENSEE, by the Massachusetts
+Institute of Technology (M.I.T.) under the following license.  By
+obtaining, using and/or copying this software, you agree that you have
+read, understood, and will comply with these terms and conditions:  
+
+Permission to use, copy, modify and distribute without fee  for  any  purpose,
+this  software and its documentation without fee or royalty is hereby granted,
+provided that you agree to comply with  the  following  copyright  notice  and
+statements,  including  the disclaimer, and that the same appear on ALL copies
+of the software and documentation, including modifications that you  make  for
+internal use or for distribution: 
+
+Copyright 1985 by the Massachusetts Institute of Technology.  All rights
+reserved.  
+
+THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS OR
+WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not limitation,
+M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE OR
+DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
+TRADEMARKS OR OTHER RIGHTS.   
+
+The name of the Massachusetts Institute of Technology or M.I.T. may NOT be
+used in advertising or publicity pertaining to distribution of the
+software.  Title to copyright in this software and any associated
+documentation shall at all times remain with M.I.T., and USER agrees to
+preserve same.  
diff --git a/decus/vmslt00a/bulletin/create.com b/decus/vmslt00a/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..9427f4fa7ad912e142ceab952d501494c8b3e982
--- /dev/null
+++ b/decus/vmslt00a/bulletin/create.com
@@ -0,0 +1,57 @@
+$ FQ = ""
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN FQ = "/SEPARATE_COMPILATION"
+$ IF F$GETSYI("VP_MASK") .NE. 0 THEN FQ = FQ + "/NOHPO"
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN0
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN1
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN2
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN3
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN4
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN5
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN6
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN7
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN8
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN9
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN10
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN11
+$ IF F$GETSYI("HW_MODEL") .LE. 1023 THEN MAC ALLMACS
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN MAC ALLMACS_AXP
+$ SET COMMAND/OBJ BULLCOM
+$ SET COMMAND/OBJ BULLMAIN
+$ CCQ = ""
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN CCQ = "/STAN=VAX"
+$ ON WARNING THEN GOTO DUMMY
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .NES. "" THEN GOTO MULTI
+$ IF F$TRNLNM("TWG$TCP") .EQS. "" THEN GOTO MULTI
+$ DEFINE VAXC$INCLUDE TWG$TCP:[NETDIST.INCLUDE],-
+                      TWG$TCP:[NETDIST.INCLUDE.SYS],-
+                      TWG$TCP:[NETDIST.INCLUDE.VMS],-
+                      TWG$TCP:[NETDIST.INCLUDE.NETINET],-
+                      TWG$TCP:[NETDIST.INCLUDE.ARPA],-
+                      SYS$LIBRARY
+$ CC'CCQ' BULL_NEWS/DEFINE=(TWG=1)
+$ GOTO LINK
+$MULTI:
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .EQS. "" THEN GOTO UCX
+$ CC'CCQ' BULL_NEWS/DEFINE=(MULTINET=1)
+$ GOTO LINK
+$UCX:
+$ IF F$TRNLNM("UCX$DEVICE") .EQS. "" THEN GOTO CMU
+$ CC'CCQ' BULL_NEWS/DEFINE=(UCX=1)
+$ GOTO LINK
+$CMU:
+$ CC'CCQ' BULL_NEWS
+$ GOTO LINK
+$DUMMY:
+$ WRITE SYS$OUTPUT "There is no C compiler available for the NEWS software."
+$ WRITE SYS$OUTPUT "BULLETIN will be assembled without that feature."
+$ FORTRAN BULL_NEWSDUMMY
+$LINK:
+$ SET NOON
+$ IF F$SEARCH("BULL_DIR:READ_BOARD.COM") .NES. "" THEN-
+  DELETE BULL_DIR:READ_BOARD.COM;*
+$ IF F$SEARCH("BULL.OLB") .NES. "" THEN DELETE BULL.OLB;*
+$ IF F$SEARCH("BULL.OLB") .EQS. "" THEN LIBRARY/CREATE BULL
+$ LIBRARY BULL *.OBJ;
+$ DELETE *.OBJ;*
+$ @BULLETIN.LNK
diff --git a/decus/vmslt00a/bulletin/debug.txt b/decus/vmslt00a/bulletin/debug.txt
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/decus/vmslt00a/bulletin/handout.txt b/decus/vmslt00a/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..5a1acd2568bdbb84c026c6f1a4994b5799554811
--- /dev/null
+++ b/decus/vmslt00a/bulletin/handout.txt
@@ -0,0 +1,268 @@
+               Introduction to BULLETIN on the Vax
+                                                  2/88 AW
+
+PUBLISHED BY THE DREW UNIVERSITY ACADEMIC COMPUTER CENTER. MAY BE
+COPIED WITH WRITING CREDIT GIVEN TO DREW UNIVERSITY.
+
+BULLETIN was written for the Public Domain by Mark London at MIT.
+
+     The BULLETIN utility permits a user to create messages for
+reading by other users.  Users may be notified upon logging on
+that new messages have been added, and what the topic of the
+messages are.  Actual reading of the messages is optional.  (See
+the command SET READNEW for info on automatic reading.)  Messages
+are automatically deleted when their expiration data has passed.
+     The program runs like VAX mail.  The different interest
+groups or BULLETIN boards are implemented in the form of
+'Folders', just like a filing cabinet.  A Folder contain various
+messages on the same general topic.  A message is a piece of text
+written by a user or staff person and added to a particular
+folder.  All users are not permitted to submit messages to all
+folders.
+
+     A message consists of an expiration date, a subject line
+and the text of the message.  BULLETIN will prompt the user for
+these things when a message is being added.
+
+     Several different folders are currently defined to
+BULLETIN.  The General Folders will be used by Computer Center
+Staff to post messages of general interest concerning the VAX to
+the user community.  If something is of an important nature, it
+will be posted in the General folder as a 'System' message.
+This is a special message type.  It will be displayed to each
+user  as they log in the first time after that message was
+posted.  This will be done automatically by BULLETIN on login.
+Once a particular system message has been displayed, it will not
+be displayed for that user on subsequent logins.
+
+Folders
+
+     Different folders have been created to contain messages on
+different topics.  Folders may be public, semi-private, or
+private.  The majority of the folders will be public.  However a
+few will be semi-private, which will mean that all users may
+read messages in the folder but not all will be able to post to
+it.  Currently, there are several folders defined:
+
+GENERAL -- system messages
+
+PUBLIC_ANNOUNCEMENTS -- Can be used by anyone to post messages
+of interest to the public
+
+On Beta:
+AIDE STATION -- Private folder for Computer Center Employees
+
+In addition on Alpha there are folders that receive electronic
+magazines, such as:
+NETMONTH --  The monthly magazine of BITNET information.
+RISKS -- Identifying the risks involved in using computers.
+INFOIBMPC -- Information about the IBM personal computers.
+INFOVAX -- Information on the Digital VAX.
+PROGRAMMING_JOURNALS-Includes MINIX, UNIX and C, Modula-2 and
+Prolog journals
+watch for new ones being added.
+
+Using BULLETIN
+
+     BULLETIN is invoked by type the command 'BULLETIN' (or BULL,
+for short) at the '$' prompt.  BULLETIN will display its prompt
+'BULLETIN>'. Help is available from DCL command level ($) or from
+within the BULLETIN program itself by typing the word 'HELP'.  To
+leave the BULLETIN program, type 'EXIT'.
+
+To see what is there
+
+     In order to see message and folders, on can use the
+'Directory' command. Upon entering BULLETIN, the user is place
+in the General folder.  If the user wishes to see which folders
+exist, the directory/folders command is used. for example:
+typing:
+
+     BULLETIN> directory/folders
+
+will make a display like:
+
+      Folder                       Owner
+     *GENERAL                      SYSTEM
+     *PUBLIC_ANNOUNCEMENTS         BBEYER
+      NETMONTH                     BITNET
+     *VAX_SIG                      BBEYER
+
+An asterisk (*) next to the folder name indicates you have unread
+messages in that folder.
+
+The command 'DIRECTORY/FOLDERS/DESCRIBE' would list all available
+folders, along with a brief description of each.
+
+     To switch from one folder to another folder, the user may
+execute the 'SELECT' command.  For example, the following
+command would show what a user would do to switch to the folder
+called PUBLIC_ANNOUNCEMENTS:
+
+BULLETIN> SELECT PUBLIC_ANNOUNCEMENTS
+
+and BULLETIN would respond:
+     Folder has been set to PUBLIC_ANNOUNCEMENTS
+
+     Now the user may get a list of the messages in this folder
+by issuing the directory command with no qualifiers.
+This command, for example:
+BULLETIN> DIRECTORY
+would have bulletin respond:
+
+ #     Description               From                  Date
+ 1     CHRISTMAS PARTY           oleksiak              26-JUN-88
+ 2     Learning about BULLETIN   oleksiak              26-JUN-87
+ 3     VAX MAIL                  LLLOYD                01-Jan-87
+
+     The command 'DIR/NEW' will list just unread messages.
+
+
+Reading messages
+
+     In order to read messages in a folder, the user may type
+the read command or he/she may simply type the number of the
+message he wishes to read.  The message numbers can be acquired
+by doing the 'DIRECTORY' command.  If the user hits a carriage
+return with no input whatsoever,  BULLETIN will type the first
+message in the folder, or if there are new messages present, it
+will type the first new message in the folder.
+
+     If a folder contains the above messages (as seen by the
+'Directory' command) then these messages can be read by:
+
+BULLETIN> READ
+and BULLETIN would respond:
+
+Message number:  1                       PUBLIC_ANNOUNCEMENTS
+Description: CHRISTMAS PARTY
+Date:  26-JUN-1988 8:08:40   Expires:  1-JAN-1989 08:08:40
+
+...Body of message.....
+
+     Should the user only wish to see message number 3, he can
+enter the 'READ' command with the message number as a parameter.
+for example:
+
+BULLETIN> READ 3
+
+     There are three other useful commands that can be used at
+the 'BULLETIN>' prompt when reading messages. These are:
+
+BACK - Read the message preceding the message currently being
+read.
+
+CURRENT - Start reading the current message at the top.  This is
+useful for someone who is reading a message and wishes to reread
+it from the beginning.
+
+NEXT - Start reading from the beginning of the next message.
+This is handy if the user is reading a very long message and
+wants to skip to the next one.
+
+Saving the interesting stuff.
+
+     If the user sees something which he/she wants a copy of,
+the extract command can be use to write an ASCII copy of the
+message into a file.  This command works on the current message
+being read.  It requires the name of the file into which to save
+the message.  If the file name is not given, the user will be
+prompted for it.  For example:
+
+BULLETIN>  Read 2
+
+********** Message on Screen ********
+
+A person could then type
+BULLETIN> extract
+file:  FV.TXT
+BULLETIN>
+
+BULLETIN has now saved the contents of message number 2 into the
+file name 'FV.txt'.
+     If the file to which the user is writing already exists,
+BULLETIN will append the message to the file.  The user can
+force BULLETIN to write a new file containing only the message
+being saved by using the '/new' qualifier in the 'extract'
+command.  These messages can then be sent to other users, or
+downloaded for use in Wordperfect.  (See "Mail on the Vax", or
+"Transferring a file between a PC and the VAX").
+
+This command may be useful if you wish to transfer the message to
+your PC, perhaps using a BITNET journal message as a reference in
+a paper. Once the file is saved, you can transfer it to a PC by
+following the instructions in the handout 'Transferring files
+from the PC to the VAX of from the VAX to a PC".
+
+Adding messages
+     A user may add a message to a folder by selecting the
+folder and then using the 'ADD' command.  This is provided that
+the user is adding the message to a public folder.  The user has
+the option of giving the 'ADD' command and typing a message using
+the VAX editor or uploading a message from your PC (see
+documentation), or add a message you have extracted from VAX
+mail.  BULLETIN will prompt for the expiration date and subject
+line.  It will then add the text of the file as the body of the
+message. To add a message that is stored in a file (from MAIL or
+from your PC, for example) type:
+
+          ADD filename
+
+If the user does not specify a file name, he/she will be
+prompted to enter the body of the message.  The user may also
+use the EDT text editor by issuing the command with the
+'/EDIT'option.
+
+For example:
+BULLETIN> sel PUBLIC_ANNOUNCEMENTS
+          folder has been set to PUBLIC_ANNOUNCEMENTS
+BULLETIN> ADD MESS.TXT
+
+IT IS 10-JUL-1988 12:41:06.15.  SPECIFY WHEN THE MESSAGE SHOULD
+EXPIRE:  ENTER ABsolute TIME:  <DD-MMM-YYYY]HH:MM:SS OR DELTA
+TIME: DDD HH:MM:SS
+
+A user then type the date of expiration and press the 'return'
+button.  The time input may be ignored. For example, typing:
+20-JUL-1988 or type "10" - for ten days in the future.
+
+BULLETIN responds:
+ENTER DESCRIPTION HEADER.  LIMIT HEADER TO 53 CHARACTERS.
+
+Now the user may enter the subject of the message.
+
+BULLETIN>
+
+The above session adds the text in the file 'mess.txt' as the
+next message in the PUBLIC_ANNOUNCEMENTS Folder.  The message
+will be deleted automatically on the 20th of July as requested
+by the user adding the message.
+
+Asking BULLETIN to notify you of new messages upon logging in.
+
+     If the user wishes to get notification on login when new
+messages are in a folder, he should use the 'READNEW' option.
+This command does not force the reader to reading new messages,
+only gives notification.  To do this, 'SELECT' each folder you
+are interested in and do a 'SET READNEW' command while set to
+that folder.
+
+Example:
+
+BULLETIN> Select PUBLIC_ANNOUNCEMENTS
+folder has been set to PUBLIC_ANNOUNCEMENTS
+BULLETIN> SET READNEW
+
+Alternately, you may type SET SHOWNEW. This will just display a
+message notifying you that there are new messages.
+
+Mailing a BULLETIN message
+
+     A user may directly mail another user a message found in the
+BULLETIN.  While reading the message that he/she desires to send,
+at the 'BULLETIN>' type 'MAIL'.  The Vax will then ask to whom
+you wish to send the information too.
+
+Check the BULLETIN DISCUSSION folder on ALPHA for new additions.
+If you have comments or questions about BULLETIN, leave them
+there.
diff --git a/decus/vmslt00a/bulletin/install.com b/decus/vmslt00a/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..34427ba06e29d10e305740acd87ab2de55b4678e
--- /dev/null
+++ b/decus/vmslt00a/bulletin/install.com
@@ -0,0 +1,25 @@
+$ IF F$TRN("BULL_DIR") .EQS. ""
+$ THEN
+$   WRITE SYS$OUTPUT "ERROR: BULL_DIR has not been defined yet."
+$   WRITE SYS$OUTPUT "Assign BULL_DIR as a logical name or modify this"
+$   WRITE SYS$OUTPUT "command procedure to point to the appropriate directory."
+$   EXIT
+$ ENDIF
+$ COPY BULLETIN.EXE BULL_DIR:
+$ RUN SYS$SYSTEM:INSTALL
+BULL_DIR:BULLETIN/DEL
+BULL_DIR:BULLETIN/SHAR/OPEN/HEAD/-
+PRIV=(OPER,SYSPRV,CMKRNL,WORLD,DETACH,PRMMBX,SYSNAM)
+/EXIT
+$!
+$! NOTE: BULLETIN requires a separate help library. If you do not wish
+$! the library to be placed in SYS$HELP, modify the following lines and
+$! define the logical name BULL_HELP to be the help library directory, i.e.
+$!	$ DEFINE/SYSTEM BULL_HELP SYSD$:[NEWDIRECTORY]
+$! The above line should be placed in BULLSTART.COM to be executed after
+$! every system reboot.
+$!
+$ IF F$SEARCH("SYS$HELP:BULL.HLB") .NES. "" THEN LIBRARY/DELETE=*/HELP SYS$HELP:BULL
+$ IF F$SEARCH("SYS$HELP:BULL.HLB") .EQS. "" THEN LIBRARY/CREATE/HELP SYS$HELP:BULL
+$ LIBRARY/HELP SYS$HELP:BULL BULLCOMS1,BULLCOMS2
+$ LIBRARY/HELP SYS$HELP:HELPLIB BULLETIN
diff --git a/decus/vmslt00a/bulletin/instruct.com b/decus/vmslt00a/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..273d3e9f0845774078d0dc4f53c720256671bcb2
--- /dev/null
+++ b/decus/vmslt00a/bulletin/instruct.com
@@ -0,0 +1,6 @@
+$ BULLETIN
+ADD/PERMANENT/SYSTEM INSTRUCT.TXT/NOEDIT
+INFO ON HOW TO USE THE BULLETIN UTILITY.
+ADD/PERMANENT NONSYSTEM.TXT/NOEDIT
+INFO ON BEING PROMPTED TO READ NON-SYSTEM BULLETINS.
+EXIT
diff --git a/decus/vmslt00a/bulletin/instruct.txt b/decus/vmslt00a/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6699642154414c70118a5de434037357572300db
--- /dev/null
+++ b/decus/vmslt00a/bulletin/instruct.txt
@@ -0,0 +1,8 @@
+This message is being displayed by the BULLETIN facility.  This is a non-DEC
+facility, so it is not described in the manuals.  Messages can be submitted by
+using the BULLETIN command.  System messages, such as this one, are displayed
+in full, but can only be entered by privileged users.  Non-system messages can
+be entered by anyone, but only their topics will be displayed at login time,
+and will be prompted to optionally read them.  (This prompting feature can be
+disabled).  All bulletins can be reread at any time unless they are deleted or
+expire.  For more information, see the on-line help (via HELP BULLETIN). 
diff --git a/decus/vmslt00a/bulletin/login.com b/decus/vmslt00a/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6707834c7c17009676b16fcc320a7f4c85e77a8
--- /dev/null
+++ b/decus/vmslt00a/bulletin/login.com
@@ -0,0 +1,31 @@
+$!
+$! The following line defines the BULLETIN command.
+$!
+$ BULL*ETIN :== $BULL_DIR:BULLETIN
+$!
+$! Note: The command prompt when executing the utility is named after
+$! the executable image.  Thus, as it is presently set up, the prompt
+$! will be "BULLETIN>".  DO NOT make the command that executes the
+$! image different from the image name, or certain things will break.
+$!
+$! If you would rather define the BULLETIN command using CDU rather than
+$! defining it using a symbol, use the BULLETIN.CLD file to do so.
+$!
+$! If you want to have more than one BULLETIN database, replace BULL_DIR
+$! with the actual directory to allow redefining BULL_DIR.  
+$!
+$! The following line causes new messages to be displayed upon logging in.
+$!
+$ BULLETIN/LOGIN/REVERSE
+$!
+$! If you wish bulletins to be displayed starting with
+$! the newest rather the oldest, omit the /REVERSE qualifier.
+$! Note that for totally new users, only permanent system messages and
+$! the first non-system general message is displayed (which, if you ran
+$! INSTURCT.COM, would describe what a non-system message is).
+$! This is done so as to avoid overwhelming a new user with lots of
+$! messages upon logging in for the first time.
+$! Users who have DISMAIL enabled in the authorzation table will automatically
+$! be set to "NOLOGIN" (see HELP SET NOLOGIN).  If you wish to disable this
+$! feature, add /ALL to the /LOGIN command.
+$!
diff --git a/decus/vmslt00a/bulletin/makefile b/decus/vmslt00a/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..c5bbf6fef769c6639dfa2cd1cad6e81c46c85868
--- /dev/null
+++ b/decus/vmslt00a/bulletin/makefile
@@ -0,0 +1,82 @@
+# Makefile for BULLETIN
+ 
+Bulletin : Bulletin.Exe Bull.Hlb
+ 
+Bulletin.Exe : Bull.Olb
+   Link /NoTrace Bull.Olb/Lib /Inc=Bulletin$Main,Sys$System:Sys.Stb/Sel -
+        /NoUserlib /Exe=Bulletin.Exe,Sys$Input/Opt
+   ID="V2.5" $
+ 
+Bull.Olb : Bulletin.Obj Bulletin0.Obj Bulletin1.Obj Bulletin2.Obj  \
+           Bulletin3.Obj Bulletin4.Obj Bulletin5.Obj Bulletin6.Obj \
+           Bulletin7.Obj Bulletin8.Obj Bulletin9.Obj Bulletin10.Obj \
+           Bulletin11.Obj Bullcom.Obj Bullmain.Obj Allmacs.Obj
+   Library /Create Bull.Olb *.Obj
+   Purge /Log *.Obj,*.Exe
+ 
+Bulletin.Obj : Bulletin.For Bullfiles.Inc Bulldir.Inc Bullfolder.Inc \
+               Bulluser.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin.For
+ 
+Bulletin0.Obj : Bulletin0.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin0.For
+ 
+Bulletin1.Obj : Bulletin1.For Bulldir.Inc Bullfolder.Inc Bulluser.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin1.For
+ 
+Bulletin2.Obj : Bulletin2.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin2.For
+ 
+Bulletin3.Obj : Bulletin3.For Bulldir.Inc Bullfolder.Inc Bulluser.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin3.For
+ 
+Bulletin4.Obj : Bulletin4.For Bullfolder.Inc Bulluser.Inc Bullfiles.Inc \
+                Bulldir.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin4.For
+ 
+Bulletin5.Obj : Bulletin5.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin5.For
+ 
+Bulletin6.Obj : Bulletin6.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin6.For
+ 
+Bulletin7.Obj : Bulletin7.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin7.For
+ 
+Bulletin8.Obj : Bulletin8.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin8.For
+ 
+Bulletin9.Obj : Bulletin9.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin9.For
+ 
+Bulletin10.Obj : Bulletin10.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin10.For
+ 
+Bulletin11.Obj : Bulletin11.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin11.For
+ 
+Allmacs.Obj : Allmacs.mar
+   Macro   /NoList Allmacs.Mar
+ 
+Bullcom.Obj : Bullcom.cld
+   Set Command /Obj Bullcom.Cld
+ 
+Bullmain.Obj : Bullmain.cld
+   Set Command /Obj Bullmain.Cld
+ 
+Bull.Hlb : Bullcoms1.Hlp Bullcoms2.Hlp
+   Library /Create /Help Bull.Hlb Bullcoms1.Hlp, Bullcoms2.Hlp
+   Purge Bull.Hlb
+*.hlb :
+        lib/help/cre $*
diff --git a/decus/vmslt00a/bulletin/master.com b/decus/vmslt00a/bulletin/master.com
new file mode 100755
index 0000000000000000000000000000000000000000..112d981424b5777491b97a2ab82df7f864037a1c
--- /dev/null
+++ b/decus/vmslt00a/bulletin/master.com
@@ -0,0 +1,408 @@
+$ ! MASTER.COM - Initiate delivery of messages queued on a channel
+$ !
+$ ! Modification history and parameter definitions are at the end of this file.
+$ !
+$ set noon
+$ !
+$ ! Clean up and set up channel name, if on hold just exit
+$ !
+$ channel_name = f$edit(p1, "COLLAPSE,LOWERCASE")
+$ hold_list = "," + f$edit(f$logical("PMDF_HOLD"), "COLLAPSE,LOWERCASE") + ","
+$ if f$locate("," + channel_name + ",", hold_list) .lt. -
+     f$length(hold_list) then exit
+$ define/process pmdf_channel "''channel_name'"
+$ !
+$ ! Save state information, set up environment properly
+$ !
+$ save_directory = f$environment("DEFAULT")
+$ set default pmdf_root:[queue]
+$ save_protection = f$environment("PROTECTION")
+$ set protection=(s:rwed,o:rwed,g,w)/default
+$ save_privileges = f$setprv("NOSHARE")
+$ !
+$ if f$logical("PMDF_DEBUG") .eqs. "" then on control_y then goto out
+$ !
+$ ! Create listing of messages queued on this channel.
+$ !
+$ if p3 .eqs. "" then p3 = "1-JAN-1970"
+$ dirlst_file = "pmdf_root:[log]" + channel_name + "_master_dirlst_" + -
+  F$GETJPI ("", "PID") + ".tmp"
+$ define/process outbound 'dirlst_file'
+$ directory/noheader/notrailer/column=1/since="''p3'"/output='dirlst_file' -
+  pmdf_root:[queue]'channel_name'_*.%%;*
+$ !
+$ ! Determine whether or not connection should really be made
+$ !
+$ if p2 .nes. "POLL" .and. -
+     f$file_attributes(dirlst_file, "ALQ") .eq. 0 then goto out1
+$ !
+$ ! Handle various channels specially
+$ !
+$ if channel_name .eqs. "l" then goto local_channel
+$ if channel_name .eqs. "d" then goto DECnet_compatibility_channel
+$ if channel_name .eqs. "directory" then goto dir_channel
+$ if f$extract(0,5,channel_name) .eqs. "anje_"  then goto BITNET_channel
+$ if f$extract(0,4,channel_name) .eqs. "bit_"   then goto BITNET_channel
+$ if f$extract(0,5,channel_name) .eqs. "bull_"  then goto BULLETIN_channel
+$ if f$extract(0,3,channel_name) .eqs. "cn_"    then goto CN_channel
+$ if f$extract(0,5,channel_name) .eqs. "ctcp_"  then goto CTCP_channel
+$ if f$extract(0,3,channel_name) .eqs. "dn_"    then goto DECnet_channel
+$ if f$extract(0,6,channel_name) .eqs. "dsmtp_" then goto DSMTP_channel
+$ if f$extract(0,5,channel_name) .eqs. "etcp_"  then goto ETCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "ftcp_"  then goto FTCP_channel
+$ if f$extract(0,4,channel_name) .eqs. "ker_"   then goto KER_channel
+$ if f$extract(0,5,channel_name) .eqs. "mail_"  then goto MAIL_channel
+$ if f$extract(0,5,channel_name) .eqs. "mtcp_"  then goto MTCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "px25_"  then goto PX25_channel
+$ if f$extract(0,4,channel_name) .eqs. "tcp_"   then goto TCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "test_"  then goto TEST_channel
+$ if f$extract(0,5,channel_name) .eqs. "uucp_"  then goto UUCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "wtcp_"  then goto WTCP_channel
+$ if f$extract(0,6,channel_name) .eqs. "xsmtp_" then goto XSMTP_channel
+$ !
+$ ! This must be a PhoneNet channel (the default); set up and use MASTER
+$ !  Read the list of valid connection types for each channel.
+$ !
+$ cnt = f$integer("0")
+$ open/read/error=regular_master pmdf_data pmdf_root:[table]phone_list.dat
+$       list_loop:
+$               read/end=eof_list pmdf_data line
+$ !  Ignore comment lines.
+$               if (f$extract (0, 1, line) .eqs. "!") then -
+                        goto list_loop
+$               line = f$edit (line, "COMPRESS,LOWERCASE")
+$ !  Get the channel name from the line read.
+$               chan = f$extract (0, f$locate(" ", line), line)
+$               if (chan .nes. channel_name) then -
+$                       goto list_loop
+$ !  Get the connection name
+$               name = f$edit(f$extract(f$locate(" ",line),255,line),"COLLAPSE")
+$ !  If none, then ignore the line
+$               if name .eqs. "" then -
+                        goto list_loop
+$ !  Found at least one to try.
+$               cnt = cnt + 1
+$               @pmdf_root:[exe]all_master.com 'name'
+$               define PMDF_DEVICE TT
+$ !
+$ ! Define other logical names
+$ !
+$ define/user script             pmdf_root:[table.'channel_name']'name'_script.
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ !
+$ !   This check attempts to verify that we are in fact the owner process of
+$ !   the device, TT.  If the device is sharable, then we ignore the
+$ !   owner.
+$ !
+$ if (f$getdvi("TT","pid") .nes. f$getjpi(0,"pid")) .and. -
+     (f$getdvi("TT","shr") .eqs. "FALSE") then -
+        goto list_loop
+$ !
+$ !  Run master to deliver the mail
+$ !
+$ run pmdf_root:[exe]master
+$ exit_stat = $status
+$ !
+$ ! Activate optional cleanup script to reset terminal/modem
+$ !
+$ if f$search("pmdf_root:[exe]''name'_cleanup.com") .nes. "" then -
+     @pmdf_root:[exe]'name'_cleanup.com 'exit_stat'
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ !
+$ !  If master does not exit normally, then try a different connection.
+$ !
+$ if exit_stat .ne. 1 then goto list_loop
+$ eof_list:
+$ close pmdf_data
+$ !
+$ !  If we found at least one connection type for this channel, then skip
+$ !  the attempt to use the conventional mechanism.
+$ !
+$ if cnt .gt. 0 then goto out_phonenet
+$ !
+$ regular_master:
+$ @pmdf_root:[exe]'channel_name'_master.com
+$ define PMDF_DEVICE TT
+$ !
+$ !  Define logical names
+$ !
+$ define/user script             pmdf_root:[table]'channel_name'_script.
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ !
+$ run pmdf_root:[exe]master
+$ exit_stat = $status
+$ !
+$ !  Activate optional cleanup script to reset terminal/modem
+$ !
+$ if f$search("''channel_name'_cleanup.com") .nes. "" then -
+     @pmdf_root:[exe]'channel_name'_cleanup.com 'exit_stat'
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ !
+$ out_phonenet:
+$ if P4 .eqs. "POST" then wait 00:00:30
+$ goto out1
+$ !
+$ ! Directory channel
+$ !
+$ dir_channel:
+$ !
+$ run pmdf_root:[exe]dir_master
+$ goto out1
+$ !
+$ ! This is a DECnet channel; set up and use DN_MASTER
+$ !
+$ DECnet_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ node_name = f$edit(channel_name - "dn_", "UPCASE")
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ define/user pmdf_node          "''node_name'::""PMDF="""
+$ !
+$ run pmdf_root:[exe]dn_master
+$ goto out1
+$ !
+$ ! This is a BITNET channel; use BN_MASTER
+$ !
+$ BITNET_channel:
+$ !
+$ if channel_name .eqs. "bit_gateway" then goto BITNET_gateway
+$ run pmdf_root:[exe]bn_master
+$ goto out1
+$ !
+$ ! This is the BITNET gateway channel; use BN_GATEWAY
+$ !
+$ BITNET_gateway:
+$ !
+$ run pmdf_root:[exe]bn_gateway
+$ goto out1
+$ !
+$ ! This is a BULLETIN channel; use BULLETIN_MASTER
+$ !
+$ BULLETIN_channel:
+$ !
+$ run pmdf_root:[exe]bulletin_master
+$ goto out1
+$ !
+$ ! This is a Tektronix TCP channel; use TCP_MASTER
+$ !
+$ TCP_channel:
+$ !
+$ run pmdf_root:[exe]tcp_master
+$ goto out1
+$ !
+$ ! This is a CMU/Tektronix TCP channel; use CTCP_MASTER
+$ !
+$ CTCP_channel:
+$ !
+$ run pmdf_root:[exe]ctcp_master
+$ goto out1
+$ !
+$ ! This is a Wollongong TCP channel; use WTCP_MASTER
+$ !
+$ WTCP_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ run pmdf_root:[exe]wtcp_master
+$ goto out1
+$ !
+$ ! This is a MultiNet TCP channel; use MTCP_MASTER
+$ !
+$ MTCP_channel:
+$ !
+$ run pmdf_root:[exe]mtcp_master
+$ goto out1
+$ !
+$ ! This is a Excelan TCP channel; use ETCP_MASTER
+$ !
+$ ETCP_channel:
+$ !
+$ run pmdf_root:[exe]etcp_master
+$ goto out1
+$ !
+$ ! This is an NRC Fusion TCP channel; use FTCP_MASTER
+$ !
+$ FTCP_channel:
+$ !
+$ run pmdf_root:[exe]ftcp_master
+$ goto out1
+$ !
+$ CN_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ define/user script             pmdf_root:[table]'channel_name'_script.
+$ ! following may vary: should point to cnio's group
+$ define/table=lnm$process_directory lnm$temporary_mailbox lnm$group_000277
+$ !
+$ run/nodeb'p5' pmdf_root:[exe]cn_smtp_master
+$ goto out1
+$ !
+$ KER_channel:
+$ !
+$ ! kermit protocol is slave only. If we get here there has been a mistake.
+$ ! however we will just exit and no harm done.
+$ goto out1
+$ !
+$ ! This is a PhoneNet X25 channel; set up and use PX25_MASTER
+$ !
+$ PX25_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]'channel_name'_di_master.trn
+$ define/user ph_logfile         pmdf_root:[log]'channel_name'_ph_master.log
+$ define/user di_errfile         pmdf_root:[log]'channel_name'_di_master.log
+$ !
+$ run pmdf_root:[exe]PX25_master
+$ goto out1
+$ !
+$ ! This is a DEC/Shell channel; set up and use UUCP_MASTER
+$ !
+$ UUCP_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ uucp_to_host = channel_name - "uucp_"
+$ define/user uucp_to_host       "''uucp_to_host'"
+$ define/user uucp_current_message -
+  pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user uucp_logfile       pmdf_root:[log]'channel_name'_master.logfile
+$ !
+$ run pmdf_root:[exe]UUCP_master
+$ uupoll = "$shell$:[usr.lib.uucp]uupoll"
+$ uupoll 'uucp_to_host'
+$ goto out1
+$ !
+$ ! This is a X.25 SMTP channel; set up and use XSMTP_MASTER
+$ !
+$ XSMTP_channel:
+$ !
+$ run pmdf_root:[exe]xsmtp_master
+$ goto out1
+$ !
+$ ! This is a DECNET SMTP channel; set up and use DSMTP_MASTER
+$ !
+$ DSMTP_channel:
+$ !
+$ run pmdf_root:[exe]dsmtp_master
+$ goto out1
+$ !
+$ ! Handle delivery on the local channel, MAIL_ channels, and
+$ ! the DECnet compatibility channel
+$ !
+$ MAIL_channel:
+$ local_channel:
+$ DECnet_compatibility_channel:
+$ open/read queue_file 'dirlst_file'
+$ local_loop:
+$   read/end=exit_local_loop/error=exit_local_loop  queue_file file_to_process
+$   priv_list = f$setprv("SYSPRV, DETACH")
+$   mail/protocol=pmdf_mailshr 'file_to_process'
+$   priv_list = f$setprv(priv_list)
+$ goto local_loop
+$ !
+$ exit_local_loop:
+$ close queue_file
+$ goto out1
+$ !
+$ ! This is a SMTP test channel, use TEST_SMTP_MASTER
+$ !
+$ TEST_channel:
+$ !
+$ ! Typically some form of redirection is needed here...
+$ deassign sys$input
+$ run pmdf_root:[exe]test_smtp_master
+$ goto out1
+$ !
+$ out1:
+$ delete 'dirlst_file';*
+$ !
+$ ! Common exit point - clean up things first
+$ !
+$ out:
+$ if f$logical("OUTBOUND") .nes. "" then deassign/process outbound
+$ if f$logical("PMDF_CHANNEL") .nes. "" then deassign/process pmdf_channel
+$ if f$logical("PMDF_DATA") .nes. "" then close pmdf_data
+$ if f$logical("PMDF_DEVICE") .eqs. "" then goto restore
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ restore:
+$ !
+$ ! Restore saved stuff
+$ !
+$ set protection=('save_protection')/default
+$ set default 'save_directory'
+$ set process/priv=('save_privileges')
+$ !
+$ exit
+$ !
+$ ! Modification history:
+$ !
+$ ! This version by Ned Freed, 20-Jul-1986
+$ !
+$ ! Modified by Gregg Wonderly to allow multiple connections for each channel
+$ !   10-Oct-1986.
+$ ! Some additions by Ned Freed 30-Oct-86.
+$ ! Added CMU/Tektronix TCP channel (CTCP) /Kevin Carosso 6-Mar-1987
+$ ! Added Multinet TCP channel (MTCP) /Ned Freed 10-Mar-1987
+$ ! Added directory save/restore /Ned Freed 1-Jun-1987
+$ ! Added Excelan TCP channel (ETCP) /Ned Freed 9-Jul-1987
+$ ! Added MAIL, CNIO, KERMIT channel /Bob Smart 4-Jul-1987
+$ ! Added Warwick Jackson's PhoneNet X25 support /Ned Freed 5-Sep-87
+$ ! Added X25 SMTP channel SX25_ /Goeran Bengtsson, Mats Sundvall 24-Jul-87
+$ ! Added NRC Fusion TCP channel (FTCP) /Kevin Carosso 12-Jan-1988
+$ ! Added a variant of Randy McGee's code to put a list of channels on hold
+$ !   /Ned Freed 9-Feb-1988
+$ ! Made this procedure save and restore a little more state information
+$ !   than it used to, including default protection and privileges. Also
+$ !   moved a bunch of the logical name assignments around to eliminate
+$ !   redundant code all over the place. /Ned Freed 10-Feb-1988
+$ ! Modified to allow P3 date/time paramter. /Ned Freed 23-Feb-1988
+$ ! Added support for Dennis Boylan's UUCP channel. /Ned Freed 28-Mar-1988
+$ ! Added Robert Smart's directory channel. /Ned Freed 21-Apr-1988
+$ ! Added support for Warwick Jackson's SMTP over X.25 and SMTP over
+$ !   DECnet channels. /Ned Freed 26-May-1988
+$ ! Added P4 and P5 parameters. /Ned Freed 10-Jun-1988
+$ ! Added code to call the TEST_SMTP_MASTER for testing. /Ned Freed 1-Jul-1988
+$ ! Added preliminary support for ANJE. /Ned Freed 7-Jul-1988
+$ ! Removed extra dispatch for WTCP_ channel. /Ned Freed 3-Sep-1988
+$ ! Added dispatch for BULL_ channel. /Ned Freed 28-Nov-1988
+$ ! Cleaned up error recovered and emergency exit -- close PHONE_LIST.DAT
+$ !   file when aborting. /Ned Freed 13-Dec-1988
+$ ! Additional error recovery cleanup -- use PMDF_DEVICE instead of TT to
+$ !   allow deallocation on an abort. /Ned Freed 14-Dec-1988
+$ !
+$ ! Parameters:
+$ !
+$ !   P1 - Name of the channel whose messages are to be delivered.
+$ !   P2 - Activity type. If P2 .eqs. "POLL", establish the connection
+$ !        unconditionally, otherwise only establish the connection if
+$ !        messages are waiting in the queue.
+$ !   P3 - Earliest possible date/time for message(s). Messages older than
+$ !        this time are not processed.
+$ !   P4 - Environment. P4 .eqs. "POST" if MASTER is being called from the
+$ !        POST.COM procedure or some other procedure that invokes MASTER
+$ !        more than once. This parameter is used to insert delays before
+$ !        returning if hardware needs time to reset.
+$ !   P5 - Parameter reserved for channel-specific uses.
diff --git a/decus/vmslt00a/bulletin/mx.mai b/decus/vmslt00a/bulletin/mx.mai
new file mode 100755
index 0000000000000000000000000000000000000000..2631763f8654ed49f9badad0ba381715965fc2de
--- /dev/null
+++ b/decus/vmslt00a/bulletin/mx.mai
@@ -0,0 +1,958 @@
+$set nover
+$copy/log sys$input BUILD_MX_BULL.COM
+$deck
+$ save_verify = 'f$verify(0)'
+$!
+$!  Command file to build MX_BULL (MX SITE transport for BULLETIN)
+$!
+$ say := write sys$output
+$ if f$trnlnm("BULL_LIBRARY") .eqs. ""
+$ then	say "BULL_LIBRARY logical not defined; must point to BULL.OLB directory"
+$	exit
+$ endif
+$ say "Compiling MX_BULL...."
+$ cc mx_bull
+$ say "Linking MX_BULL...."
+$ link/notrace mx_bull,bull_library/LIB,SYS$SYSTEM:SYS.STB/SEL,sys$input/option
+SYS$SHARE:VAXCRTL.EXE/SHARE
+$ say "Build of MX_BULL.EXE completed"
+$ exit f$verify(save_verify).or.1
+$eod 
+$copy/log sys$input MX_BULL.C
+$deck
+#module MX_BULL "01-001"
+/*
+ *
+ *  Program:	MX_BULL
+ *
+ *  Author:	Hunter Goatley
+ *		Academic Computing, STH 226
+ *		Western Kentucky University
+ *		Bowling Green, KY 42101
+ *		goathunter@wkuvx1.bitnet
+ *		502-745-5251
+ *
+ *  Date:	March 8, 1991
+ *
+ *  Functional description:
+ *
+ *	This program serves as an MX SITE transport to transfer incoming
+ *	mail files to UALR's BULLETIN.
+ *
+ *	The MX_SITE delivery agent takes messages routed to a SITE path and
+ *	feeds them into a subprocess that executes a command procedure named
+ *	MX_EXE:SITE_DELIVER.COM.  There are three parameters passed to the
+ *	the command procedure:
+ *
+ *		P1	- The name of a temporary file containing the message
+ *			  text, including all of the RFC822 headers
+ *			  (corresponding to the DATA part of an SMTP
+ *			  transaction).
+ *		P2	- The name of a temporary file containing a list of
+ *			  a messages recipients, which corresponds to the
+ *			  RCPT_TO addresses of an SMTP transaction.
+ *		P3	- The RFC822 address of the sender of the message,
+ *			  which corresponds to the MAIL FROM address of an
+ *			  SMTP transaction.
+ *
+ *	This program expects the same parameters, except that the third
+ *	parameter is optional.  If the third parameter is omitted, BULLETIN
+ *	will scan the RFC822 headers in the message for a "From:" line.
+ *	If the third parameter is specified, it is expected to be a file
+ *	specification.  It is assumed that SITE_DELIVER.COM has written the
+ *	address to this file.
+ *
+ *	The logical MX_BULLETIN_POSTMASTER can be defined as a local
+ *	username to receive error notices.  If BULLETIN returns an error
+ *	while trying to add a message, and the MX_BULLETIN_POSTMASTER
+ *	is defined as a valid local username, the message will be mailed
+ *	to that user for further handling.
+ *
+ *	MX_BULLETIN_POSTMASTER must be defined system-wide in executive mode:
+ *
+ *		$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
+ *
+ *  Modification history:
+ *
+ *	01-001		Hunter Goatley		14-MAR-1991 14:41
+ *		Added scan_for_from_line, which scans the message's RFC822
+ *		headers for the "From:" line.  General cleanup on a few
+ *		routines.  MX_BULL now provides an RESPOND-able address in
+ *		BULLETIN.
+ *
+ *	01-000		Hunter Goatley		 8-MAR-1991 07:20
+ *		Genesis.
+ *
+ */
+
+/*  Include all needed structures and constants  */
+
+#include descrip
+#include lib$routines
+#include libdef
+#include lnmdef
+#include maildef
+#include rms
+#include ssdef
+#include str$routines
+#include string
+
+/* Declare the external BULLETIN routines that we call */
+
+unsigned long int INIT_MESSAGE_ADD();
+unsigned long int WRITE_MESSAGE_LINE();
+unsigned long int FINISH_MESSAGE_ADD();
+
+/* Define some macros to make things a little easier */
+
+#define rms_get(rab) ((rms_status = SYS$GET(rab)))
+#define err_exit(stat) {traceerr(stat); return(stat);}
+#define vms_errchk2() if(!(vms_status&1)) err_exit(vms_status);
+#define vms_errchk(func) {vms_status=func; vms_errchk2();}
+
+#define tracemsg(msg) if (trace) printf("MX_BULL: %s\n",msg);
+#define traceerr(msg) if (trace) printf("MX_BULL: Error status %%X%08x\n",msg);
+
+/* Define some global variables to make things easy */
+
+struct FAB msgfab;				/* FAB for message text */
+struct RAB msgrab;				/* RAB for message text */
+struct FAB rcptfab;				/* FAB for recipients file */
+struct RAB rcptrab;				/* RAB for recipients file */
+struct FAB fromfab;				/* FAB for FROM file */
+struct RAB fromrab;				/* RAB for FROM file */
+char msgbuf[512];				/* Input buffer for msgrab */
+char rcptbuf[512];				/* Input buffer for rcptrab */
+char frombuf[512];				/* Input buffer for frombuf */
+short trace;
+unsigned long int rms_status;			/* Status of RMS calls */
+unsigned long int vms_status;			/* Status of other calls */
+
+static $DESCRIPTOR(lnm_table,"LNM$SYSTEM_TABLE");
+
+#define itmlstend {0,0,0,0}			/* An empty item list */
+typedef struct itmlst				/* An item list structure */
+{
+  short buffer_length;
+  short item_code;
+  long buffer_address;
+  long return_length_address;
+} ITMLST;
+
+ITMLST
+  nulllist[] = {itmlstend};
+
+ITMLST
+  address_itmlst[] = {				/* MAIL$SEND_ADD_ADDRESS */
+	{0, MAIL$_SEND_USERNAME, 0, 0},
+	itmlstend},
+  bodypart_itmlst[] = {				/* MAIL$SEND_ADD_BODYPART */
+	{0, MAIL$_SEND_RECORD, 0, 0},
+	itmlstend},
+  attribute_itmlst[] = {			/* MAIL$SEND_ADD_ATTRIBUTE */
+	{0, MAIL$_SEND_TO_LINE, 0, 0},
+	{0, MAIL$_SEND_FROM_LINE, 0, 0},
+	{0, MAIL$_SEND_SUBJECT, 0, 0},
+	itmlstend}
+  ;
+
+ITMLST
+  trnlnm_itmlst[] = {				/* $TRNLNM item list */
+	{0, LNM$_STRING, 0, 0},
+	itmlstend}
+  ;
+
+
+/*
+ *
+ *  Function:	open_file_rms
+ *
+ *  Functional description:
+ *
+ *	This routine opens a sequential text file in VMS "normal text" file
+ *	format.  It uses RMS to open the file.
+ *
+ *  Inputs:
+ *
+ *	infab	- Address of the input FAB
+ *	inrab	- Address of the input RAB
+ *	buff	- Address of the input buffer
+ *	filename - Address of the filename to open (ASCIZ)
+ *
+ *  Outputs:
+ *
+ *	fab and rab are modified if file is opened.
+ *
+ *  Returns:
+ *
+ *	RMS status
+ *
+ */
+unsigned long int
+open_file_rms (struct FAB *infab, struct RAB *inrab, char *buff, char *filename)
+{
+    unsigned long int rms_status;
+
+    *infab = cc$rms_fab;			/* Initialize the FAB */
+    *inrab = cc$rms_rab;			/* Initialize the RAB */
+    infab->fab$b_fns = strlen(filename);	/* Set filename length */
+    infab->fab$l_fna = filename;		/* Set filename address */
+    infab->fab$b_fac = FAB$M_GET;		/* GET access only */
+    infab->fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
+    inrab->rab$l_fab = infab;			/* Let RAB point to FAB */
+    inrab->rab$b_rac = RAB$C_SEQ;		/* Sequential file access */
+    inrab->rab$w_usz = 512;			/* Record size is 512 bytes */
+    inrab->rab$l_ubf = buff;			/* Read to this buffer */
+
+    rms_status = SYS$OPEN (infab);		/* Open the file */
+    if (!(rms_status & 1))			/* If an error occurs, return */
+	return (rms_status);			/* ... a status */
+    rms_status = SYS$CONNECT (inrab);		/* Connect the RAB */
+    return (rms_status);			/* Return the RMS status */
+}
+
+/*
+ *
+ *  Function:	init_sdesc
+ *
+ *  Functional description:
+ *
+ *	Initialize a static string descriptor.
+ *
+ *  Inputs:
+ *
+ *	sdesc	- Address of the descriptor to initialize
+ *		  (of type struct dsc$descriptor_s)
+ *	string	- Address of null-terminated string the descriptor describes
+ *
+ *  Outputs:
+ *
+ *	sdesc	- Descriptor passed as sdesc is initialized
+ *
+ */
+void
+init_sdesc (struct dsc$descriptor_s *sdesc, char *string)
+{
+    sdesc->dsc$w_length = strlen(string);	/* Set the length	*/
+    sdesc->dsc$b_dtype = DSC$K_DTYPE_T;		/* Type is text		*/
+    sdesc->dsc$b_class = DSC$K_CLASS_S;		/* Class is static	*/
+    sdesc->dsc$a_pointer = string;		/* Point to the string	*/
+}
+
+/*
+ *
+ *  Function:	add_to_bulletin_folder
+ *
+ *  Functional description:
+ *
+ *	Adds a message to a BULLETIN folder by calling the external
+ *	BULLETIN routines INIT_MESSAGE_ADD, WRITE_MESSAGE_LINE, and
+ *	FINISH_MESSAGE_ADD.
+ *
+ *	The following constants are (may be) passed to INIT_MESSAGE_ADD:
+ *
+ *		Subject = "" 	Causes BULLETIN to scan RFC822 headers for
+ *				a "Subject:" or "Subj:" line
+ *		From = "MX%"	Causes BULLETIN to scan RFC822 headers for
+ *				a "Reply-to:" or "From:" line
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - RMS status of call to INIT_MESSAGE_ADD
+ *
+ */
+unsigned long int
+add_to_bulletin_folder(struct RAB *filerab, void *folder, void *from)
+{
+    unsigned long int bull_status;	/* Status from INIT_MESSAGE_ADD */
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    static $DESCRIPTOR(subject,"");	/* Subject is "" */
+
+    /* Call BULLETIN routine to initialize adding the message */
+
+    INIT_MESSAGE_ADD (folder, from, &subject, &bull_status);
+
+    if (!(bull_status & 1)){					/* Error? */
+	return(bull_status);
+    }
+
+    /*	Loop reading message lines until end-of-file.  For each line read,
+	create a string descriptor for it and call the BULLETIN routine to
+	add the line. */
+
+    while (rms_get(filerab) != RMS$_EOF){		/* Loop until EOF */
+	filerab->rab$l_rbf[filerab->rab$w_rsz] = 0;	/* End byte = NULL */
+	init_sdesc(&msg_line, filerab->rab$l_rbf);	/* Now build desc. */
+	WRITE_MESSAGE_LINE (&msg_line);			/* Add to BULLETIN */
+    }
+
+    FINISH_MESSAGE_ADD();		/* Call BULLETIN routine to finish */
+
+    tracemsg("Message added to folder");
+    return(SS$_NORMAL);			/* Return success to caller */
+}
+
+
+/*
+ *
+ *  Function:	scan_for_from_line
+ *
+ *  Functional description:
+ *
+ *	The routine scans the message's RFC822 headers for the "From:" line.
+ *	It parses out the address by extracting the <address>.
+ *
+ *	This routine was necessary because letting BULLETIN find the "From:"
+ *	line was resulting in a non-RESPONDable address for MX.  For example,
+ *	BULLETIN was creating:
+ *
+ *		From: MX%"Hunter Goatley, WKU <goathunter@WKUVX1.BITNET>"
+ *
+ *	but MX needs
+ *
+ *		From: MX%"<goathunter@WKUVX1.BITNET>"
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *
+ *  Outputs:
+ *
+ *	final_from - Address of a character buffer to receive the final address
+ *
+ *  Returns:
+ *
+ *	unsigned long int - binary success/failure status
+ *
+ *  Side effects:
+ *
+ *	The message file is rewound so that subsequent GETs start at the
+ *	beginning of the message.
+ *
+ */
+unsigned long int
+scan_for_from_line(struct RAB *filerab, char *final_from)
+{
+    unsigned long int scan_status;	/* Status from INIT_MESSAGE_ADD */
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    char whole_from_line[512];		/* The assembled "From:" line */
+    char *filebuffer;			/* Pointer to the input buffer */
+    int i, j, x;			/* Work variables */
+
+    scan_status = SS$_NORMAL;			/* Assume success */
+    whole_from_line[0] = '\0';			/* Initialize work buffer */
+
+    /*	Loop reading message lines until end-of-file or first null line,
+	which should signal the end of the RFC822 header.  For each line read,
+	check to see if we've located the "From:" line.
+    */
+
+    filebuffer = filerab->rab$l_ubf;			/* Init buffer ptr */
+    while ((rms_get(filerab) != RMS$_EOF) &&		/* Loop until EOF */
+	   ((x = filerab->rab$w_rsz) != 0)){		/* or null record */
+	filebuffer[x] = '\0';				/* Set NULL byte */
+	if (strncmp(filebuffer,"From:",5)==0){		/* Is it the "From:"? */
+
+	   /* Found "From:" line */
+	   tracemsg("Found \042From:\042 line in RFC822 header");
+	   strcpy(whole_from_line,filebuffer);		/* Copy to work buff */
+
+	   /* The "From:" line may actually be split over several lines.
+	      In such cases, the remaining lines are indented by 6 spaces.
+	      To handle this, loop reading records until one is read that
+	      doesn't begin with a blank.  As each record is read, it is
+	      trimmed and tacked on to whole_from_line, so we end up with
+	      the entire "From:" line in one buffer.  */
+
+	   while((rms_get(filerab) != RMS$_EOF) &&	/* Read rest of From: */
+		 (filebuffer[0] == ' ')){		/* ... line */
+	      for (i = 0; filebuffer[i] == ' '; ++i);	/* Step over blanks */
+	      strcat(whole_from_line,&filebuffer[i]);	/* Tack it on end */
+	   }
+
+	   /* Now have the whole "From:" line in whole_from_line.  Since
+	      the real address is enclosed in "<>", look for it by
+	      searching for the last "<" and reading up to the ">".  */
+
+	   i = strrchr(whole_from_line,'<');		/* Find last "<" */
+	   if (i != 0){					/* Found it.... */
+		j = strchr(i,'>');			/* Find last ">" */
+	        j = j-i+1;				/* Calc addr length */
+	   }
+	   else{
+		j = strlen(whole_from_line)-6;		/* Don't count From: */
+		i = &whole_from_line + 6;		/* in string length */
+	   }
+	   if (j < 0){					/* If neg., error */
+		tracemsg("Error - unable to locate from address");
+		strcpy(final_from,"");			/* Return null string */
+		scan_status = 0;			/* Set error status */
+	   }
+	   else {
+		tracemsg("Found sender's address in RFC822 header");
+		strncpy(final_from, i, j);		/* Copy to caller */
+	   }	
+	}
+    }
+
+    SYS$REWIND(filerab);		/* Rewind the file to the beginning */
+    return(scan_status);		/* Return success to caller */
+}
+
+
+/*
+ *
+ *  Function:	forward_to_postmaster
+ *
+ *  Functional description:
+ *
+ *	If an error occurs trying to write a message to a BULLETIN folder,
+ *	this routine is called to forward the message to the local
+ *	postmaster.
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *	status	- Address of longword containing the BULLETIN error code
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - binary status of call to INIT_MESSAGE_ADD
+ *
+ *  Side effects:
+ *
+ *	The message file is rewound so that subsequent calls to this routine
+ *	can be made (in case the message is to be written to several folders).
+ *
+ */
+unsigned long int
+forward_to_postmaster(struct RAB *filerab, void *folder, void *from, int status)
+{
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    struct dsc$descriptor_s subject;
+    char subject_buf[256];
+    char postmaster[256];   int postmaster_len;
+    char status_msg_buf[256];   int status_msg_len;
+    struct dsc$descriptor_s status_msg;
+    static $DESCRIPTOR(faostr,"Failed BULLETIN message for folder !AS");
+    static $DESCRIPTOR(MXBULL,"MX->SITE (BULLETIN delivery)");
+    static $DESCRIPTOR(postmaster_lnm,"MX_BULLETIN_POSTMASTER");
+    int send_context = 0;  int x;  int y;
+
+    static char *error_msgs[] = {
+	{"Error delivering message to BULLETIN folder.  BULLETIN error status:"},
+	{""},
+	{""},
+	{"Original message text follows:"},
+	{"--------------------------------------------------"}
+    };
+
+    trnlnm_itmlst[0].buffer_length = 255;
+    trnlnm_itmlst[0].buffer_address = &postmaster;
+    trnlnm_itmlst[0].return_length_address = &postmaster_len;
+
+    SYS$TRNLNM( 0, &lnm_table, &postmaster_lnm, 0, trnlnm_itmlst);
+    if (postmaster_len == 0)		/* If logical is not defined, */
+	return(SS$_NORMAL);		/* then pretend it worked     */
+
+    tracemsg("Forwarding message to local postmaster....");
+    subject.dsc$w_length = 255;
+    subject.dsc$a_pointer = &subject_buf;
+    SYS$FAO(&faostr, &subject, &subject, folder);	/* Format the subject */
+
+    address_itmlst[0].buffer_length = postmaster_len;		   /* To: */
+    address_itmlst[0].buffer_address = &postmaster;		   /* To: */
+    attribute_itmlst[0].buffer_length = postmaster_len;		   /* To: */
+    attribute_itmlst[0].buffer_address = &postmaster;		   /* To: */
+    attribute_itmlst[1].buffer_length = MXBULL.dsc$w_length;	   /* From: */
+    attribute_itmlst[1].buffer_address = MXBULL.dsc$a_pointer;	   /* From: */
+    attribute_itmlst[2].buffer_length = subject.dsc$w_length;	   /* Subject:*/
+    attribute_itmlst[2].buffer_address = subject.dsc$a_pointer;	   /* Subject:*/
+
+    vms_errchk(mail$send_begin(&send_context, &nulllist, &nulllist));
+    vms_errchk(mail$send_add_address(&send_context, &address_itmlst,
+			&nulllist));
+    vms_errchk(mail$send_add_attribute(&send_context, &attribute_itmlst,
+			&nulllist));
+
+    for (x = 0; x < 5; x++){
+	bodypart_itmlst[0].buffer_length = strlen(error_msgs[x]);
+	bodypart_itmlst[0].buffer_address = error_msgs[x];
+	vms_errchk(mail$send_add_bodypart(&send_context,
+		&bodypart_itmlst, &nulllist));
+	if (x == 1){
+	  status_msg.dsc$w_length = 256;
+	  status_msg.dsc$b_dtype = DSC$K_DTYPE_T;
+	  status_msg.dsc$b_class = DSC$K_CLASS_S;
+	  status_msg.dsc$a_pointer = &status_msg_buf;
+	  y = SYS$GETMSG (status, &status_msg, &status_msg, 15, 0);
+	  if (!(y & 1))
+	     sprintf(status_msg_buf,"Error code is %%X%08x",status);
+	  else
+	     status_msg_buf[status_msg.dsc$w_length] = '\0';
+	  bodypart_itmlst[0].buffer_length = strlen(status_msg_buf);
+	  bodypart_itmlst[0].buffer_address = &status_msg_buf;
+	  vms_errchk(mail$send_add_bodypart(&send_context,&bodypart_itmlst,
+		&nulllist));
+	}
+    }
+
+    while (rms_get(filerab) != RMS$_EOF){		/* Loop until EOF */
+	bodypart_itmlst[0].buffer_length = filerab->rab$w_rsz;
+	bodypart_itmlst[0].buffer_address = filerab->rab$l_rbf;
+	vms_errchk(mail$send_add_bodypart(&send_context,
+		&bodypart_itmlst, &nulllist));
+    }
+
+    vms_errchk(mail$send_message(&send_context, &nulllist, &nulllist));
+    vms_errchk(mail$send_end(&send_context, &nulllist, &nulllist));
+
+    tracemsg("Message forwarded to postmaster....");
+}
+
+
+/*
+ *
+ *  Function:	log_accounting
+ *
+ *  Functional description:
+ *
+ *	This routine will write an accounting record for the message.
+ *
+ *  Inputs:
+ *
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *	status	- Address of longword containing the BULLETIN error code
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - RMS status
+ *
+ */
+unsigned long int
+log_accounting(void *folder, void *from, int bull_status)
+{
+    struct FAB accfab;
+    struct RAB accrab;
+    static $DESCRIPTOR(MX_BULL_ACCNTNG,"MX_BULLETIN_ACCNTNG");
+    static $DESCRIPTOR(faostr,
+	"!%D MX_BULL: FOLDER=\042!AS\042, ORIGIN=\042!AS\042, STATUS=%X!XL");
+    char outbufbuf[256];
+    struct dsc$descriptor_s outbuf = {256, DSC$K_DTYPE_T, DSC$K_CLASS_S,
+		 &outbufbuf};
+
+    int status;
+    static char bullacc[] = "MX_BULLETIN_ACC";
+    static char bullaccdef[] = "MX_SITE_DIR:.DAT";
+
+    status = SYS$TRNLNM( 0, &lnm_table, &MX_BULL_ACCNTNG, 0, 0);
+    if (!(status & 1))
+	return(SS$_NORMAL);
+
+    tracemsg("Writing accounting information to accounting log....");
+    accfab = cc$rms_fab;
+    accrab = cc$rms_rab;
+    accfab.fab$b_fns = strlen(bullacc);		/* Set filename length */
+    accfab.fab$l_fna = &bullacc;		/* Set filename address */
+    accfab.fab$b_dns = strlen(bullaccdef);	/* Set filename length */
+    accfab.fab$l_dna = &bullaccdef;		/* Set filename address */
+    accfab.fab$b_fac = FAB$M_PUT;		/* PUT access only */
+    accfab.fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
+    accfab.fab$b_rfm = FAB$C_VAR;		/* Variable length records */
+    accfab.fab$b_rat = FAB$M_CR;		/* Normal "text" rat */
+    accrab.rab$l_fab = &accfab;			/* Let RAB point to FAB */
+    accrab.rab$b_rac = RAB$C_SEQ;		/* Sequential file access */
+
+    status = SYS$OPEN (&accfab);		/* Try to open the file */
+    if (status & 1)				/* Success? */
+	accrab.rab$l_rop = RAB$M_EOF;		/* Set to EOF */
+    else					/* Couldn't open, so create */
+	status = SYS$CREATE (&accfab);		/* ... a new one */
+    if (status & 1){				/* If either was OK... */
+	status = SYS$CONNECT (&accrab);		/* Connect the RAB */
+	if (status == RMS$_EOF)			/* RMS$_EOF status is OK */
+	   status = RMS$_NORMAL;		/* Change it to NORMAL */
+	if (!(status & 1)){			/* If any error occurred */
+	   tracemsg("Unable to open accounting file");
+	   traceerr(status);
+	   SYS$CLOSE (&accfab);			/* Close the file */
+	   return(status);			/* And return the error */
+	}
+    }
+    else
+	return(status);
+
+    SYS$FAO(&faostr, &outbuf, &outbuf, 0, folder, from, bull_status);
+    accrab.rab$w_rsz = outbuf.dsc$w_length;
+    accrab.rab$l_rbf = outbuf.dsc$a_pointer;
+    SYS$PUT (&accrab);
+    SYS$CLOSE (&accfab);
+}
+
+/*
+ * 
+ *  Main routine
+ *
+ */
+main(int argc, char *argv[])
+{
+  struct dsc$descriptor_s folder;	/* Descriptor for the folder name */
+  struct dsc$descriptor_s from_user;	/* Descriptor for "From:" line */
+  static $DESCRIPTOR(MX_SITE_DEBUG,"MX_SITE_DEBUG");
+
+  char *from_line;			/* Pointer to dynamic "From:" buffer */
+  char *folder_name;			/* Pointer to folder name in rcptbuf */
+  char *atsign;				/* Pointer to "@" in rcptbuf */
+  int  x;				/* Work variable */
+  unsigned long int bull_status;	/* Status from add_to_bulletin_folder */
+
+  --argc;				/* Don't count the program name */
+  if ((argc != 2) && (argc != 3)) {	/* If too many or too few args, */
+    exit(LIB$_WRONUMARG);		/* ...  exit with error status  */
+  }
+
+  vms_status = SYS$TRNLNM( 0, &lnm_table, &MX_SITE_DEBUG, 0, 0);
+  if (vms_status & 1)
+    trace = 1;
+  else
+    trace = 0;
+
+  /*  Open all input files  */
+
+  tracemsg("Opening message file....");
+  vms_errchk(open_file_rms (&msgfab, &msgrab, &msgbuf, argv[1]));
+  tracemsg("Opening recipients file....");
+  vms_errchk(open_file_rms (&rcptfab, &rcptrab, &rcptbuf, argv[2]));
+
+  if (argc == 2){
+     tracemsg("Using sender address from RFC822 headers....");
+     scan_for_from_line(&msgrab, &frombuf);
+  }
+  else {
+     tracemsg("Opening sender address file....");
+     vms_errchk(open_file_rms (&fromfab, &fromrab, &frombuf, argv[3]));
+
+     tracemsg("Reading sender address from file....");
+     rms_get(&fromrab);			/* Read the from line */
+     if (!(rms_status & 1))		/* Exit if an error occurred */
+	err_exit(rms_status);
+
+     /* Set the end of the record read, then initialize the descriptor for it */
+     frombuf[fromrab.rab$w_rsz] = 0;
+
+     SYS$CLOSE(&fromfab);
+  }						/* End of "if (argc == 2)"... */
+
+  /* frombuf now has the sender's address in it */
+
+  if (strlen(frombuf) == 0) {
+	tracemsg("Unable to find sender's address, using MX%");
+	init_sdesc(&from_user, "MX%");
+  }
+  else{
+
+     /* Now add the MX% prefix and the double quotes */
+     from_line = malloc(4 + strlen(frombuf) + 1 + 1);	/* Allocate memory */
+
+     /* Make the string repliable through MX by adding MX%"" to it */
+     strcpy(from_line,"MX%\042");
+     strcat(from_line,frombuf);
+     strcat(from_line,"\042");
+     if (trace)
+	printf("MX_BULL: Sender's address is %s\n", from_line);
+     init_sdesc (&from_user, from_line);	/* Create a string descriptor */
+  }
+  /*
+    Read through all the recipients, writing the message to all BULLETIN
+    folders (identified by checking for @BULLETIN in the address).
+  */
+  rms_get(&rcptrab);				/* Read a recipient */
+  while ((rms_status & 1) & (rms_status != RMS$_EOF)){
+     tracemsg("Looking for BULLETIN folder....");
+     folder_name = &rcptbuf;			/* Point to receipt buffer */
+     if (folder_name[0] == '<'){		/* If line begins with "<" */
+	++folder_name;				/*  bump over it and check */
+	atsign = strchr(rcptbuf,'@');		/*  for a "@"		   */
+	if (atsign != 0){			/* If "@" was found,	   */
+	  if (strncmp(atsign,"@BULLETIN",9)==0){/* Is it @BULLETIN?	   */
+	    x = atsign - folder_name;		/* Length of folder name   */
+	    folder_name[x] = 0;			/* Terminate folder name   */
+	    init_sdesc (&folder, folder_name);	/* Initialize descriptor   */
+	    str$upcase(&folder, &folder);	/* Convert to uppercase    */
+	    if (trace)
+		printf("MX_BULL: Found BULLETIN folder \042%s\042....\n",
+			folder_name);
+	    tracemsg("Adding message to BULLETIN folder....");
+	    bull_status = add_to_bulletin_folder (&msgrab, &folder, &from_user);
+	    if (!(bull_status & 1)){
+		 traceerr(bull_status);
+		 vms_errchk(forward_to_postmaster(&msgrab, &folder, &from_user,
+				bull_status));
+	    }
+	    log_accounting(&folder, &from_user, bull_status);
+	    SYS$REWIND(&msgrab);	/* Rewind the file for next folder */
+
+	  }
+	}
+      }
+      rms_get(&rcptrab);		/* Read next recipient */
+  }
+
+
+  /* Close the RMS files */
+
+  SYS$CLOSE(&msgfab);  SYS$CLOSE(&rcptfab);
+
+  tracemsg("BULLETIN message processed");
+  exit(SS$_NORMAL);		/* Always return success */
+
+}
+$eod 
+$copy/log sys$input MX_BULL.TXT
+$deck
+                                    MX_BULL
+                             An MX SITE transport
+                                March 14, 1991
+
+MX_BULL is a transport between MX and BULLETIN, a VMS bulletin board program
+by Mark London at MIT.  It is designed to be called as an MX SITE transport,
+letting MX write messages into BULLETIN folders as they are processed, instead
+of routing the messages to MAIL.MAI files for each folder.
+
+The following files make up the MX_BULL distribution:
+
+   BUILD_MX_BULL.COM		Command procedure to build MX_BULL.EXE
+   MX_BULL.C			VAX C source code for MX_BULL
+   MX_BULL.TXT			This file
+   MX_BULL_SITE_DELIVER.COM	SITE_DELIVER.COM for MX_BULL
+
+The current version is 01-001.
+
+
+WHAT IS BULLETIN?
+-----------------
+BULLETIN is a VMS bulletin board written by Mark London at MIT that allows
+multiple users to access a common message base.  Messages are divided into
+folders, which work much like VMS Mail folders.  Using MX_BULL, messages can
+be routed from Internet/Bitnet mailing lists directly to BULLETIN folders,
+allowing all (or some) users on a system to access the mailing lists without
+individual subscriptions.  This can cut down on the number of incoming
+Bitnet/Internet mail messages significantly, since only one copy of a message
+need be sent to a site.
+
+BULLETIN can be found on a number of the DECUS VAX SIG tapes, including the
+Fall 1990 tapes.  It can also be retrieved by sending a mail message to
+BULLETIN@NERUS.PFC.MIT.EDU.  The body of the message must contain one of
+the following commands:
+
+        SEND ALL        Sends all bulletin files.
+        SEND filename   Sends the specified file.
+        BUGS            Sends a list of the latest bug fixes.
+        HELP or INFO    Sends a brief description of BULLETIN.
+
+
+BUILDING MX_BULL.EXE
+--------------------
+MX_BULL is written in VAX C and can be compiled by executing BUILD_MX_BULL.COM.
+
+MX_BULL must be linked with the BULLETIN object library, BULL.OLB.  The
+build procedure for MX_BULL expects the logical BULL_LIBRARY to point to the
+BULLETIN library.  You must define this logical (or edit the .COM file)
+before building MX_BULL.
+
+
+INSTALLING MX_BULL
+------------------
+To install MX_BULL, perform the following steps:
+
+1.  Using MCP, define a path named BULLETIN as a SITE transport:
+
+	MCP> DEFINE PATH "BULLETIN" SITE
+
+2.  Using MCP, define a rewrite rule early in the list (this should actually
+    be done using CONFIG.MCP so that the order is correct):
+
+	MCP> DEFINE REWRITE_RULE "<{folder}@BULLETIN>" "<{folder}@BULLETIN>"
+
+3.  If you don't have a SITE transport already defined, simply copy
+    MX_BULL_SITE_DELIVER.COM to MX_EXE:SITE_DELIVER.COM.
+
+    If you do have a SITE transport defined, you'll need to merge the MX_BULL
+    stuff into the existing MX_EXE:SITE_DELIVER.COM.
+
+4.  Reset the MX routers by using MCP RESET/ALL, or shutting down MX and
+    restarting it.
+
+Once these steps have been completed, MX_BULL is set up to begin delivering
+messages to BULLETIN.
+
+
+ROUTING MESSAGES TO BULLETIN
+----------------------------
+Messages are routed to BULLETIN folders by addressing mail to
+MX%"folder@BULLETIN", where "folder" is the name of the target BULLETIN
+folder.  For example, the following commands would send a message from VMS
+Mail to the BULLETIN folder GENERAL (on the local system):
+
+	$ MAIL
+	MAIL> SEND
+	To:     MX%"GENERAL@BULLETIN"
+	Subj:   This is a test....
+	.....
+
+The message is sent to the MX router, which in turn sends it to the MX SITE
+agent, since the @BULLETIN path was defined as a SITE path.
+
+To facilitate the automatic delivery of messages to BULLETIN folders, you
+should set up forwarding addresses for each of the BULLETIN folders:
+
+	MAIL> SET FORWARD/USER=GENERAL MX%"""GENERAL@BULLETIN"""
+	MAIL> SET FORWARD/USER=MX-LIST MX%"""MX-LIST@BULLETIN"""
+
+Mail addressed to GENERAL or MX-LIST will automatically be forwarded to
+BULLETIN via MX_BULL.
+
+To subscribe to a Bitnet/Internet mailing list and have the messages delivered
+to BULLETIN, use MX's MLFAKE to send a subscription request on behalf of the
+BULLETIN folder.  For example, the user to specify would be:
+
+	MLFAKE/USER=MX-LIST ....
+
+(Alternatively, you could create a dummy account named MX-LIST (or whatever
+the list name is) that exists only long enough to send the request via MAIL.)
+
+Once added to the lists, incoming mail addressed to MX-LIST will get forwarded
+to MX%"MX-LIST@BULLETIN", which will invoke MX_BULL.  For example, an incoming
+message to my local BULLETIN folder would be addressed to:
+
+	MX-LIST@WKUVX1.bitnet
+
+Since I have MX-LIST forwarded to MX%"MX-LIST@BULLETIN", the message is routed
+to the BULLETIN folder.
+
+To try to illustrate the process, assume the node is WKUVX1.bitnet.  We've
+subscribed a fake local user, INFO-VAX, to the MX mailing list; mail forwarding
+has been set up for INFO-VAX to send it to MX%"INFO-VAX@BULLETIN".  When mail
+arrives addressed to INFO-VAX@WKUVX1.BITNET, the MX Router passes the message
+to the Local agent, which discovers that the mail is forwarded to
+MX%"INFO-VAX@BULLETIN".  The message is then sent back to the Router, which
+finds that BULLETIN is defined as a SITE path, so the message is passed to
+MX->SITE, which in turn calls MX_BULL.
+
+
+MX_BULL ACCOUNTING AND DEBUGGING
+--------------------------------
+MX_BULL accounting is enabled with the system logical MX_BULLETIN_ACCNTNG:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_ACCNTNG TRUE
+
+This will cause MX_BULL to create MX_SITE_DIR:MX_BULLETIN_ACC.DAT.  The
+logical MX_BULLETIN_ACC can be defined system-wide to change the name of the
+file:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_ACC LOCALDISK:[DIR]MX_BULL.ACCOUNTING
+
+To generate debugging logs in MX_SITE_DIR:, define the system logical
+MX_SITE_DEBUG.
+
+
+ERRORS WRITING TO BULLETIN
+--------------------------
+By default, MX_BULL_SITE_DELIVER.COM always returns success to the MX SITE
+agent.  This was done to avoid bouncing network mail back to a mailing list.
+In order to be notified in case of problems writing the message to BULLETIN,
+you can define a system logical MX_BULLETIN_POSTMASTER to be a local
+username to receive failed MX_BULL transactions:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
+
+If BULLETIN returns an error, MX_BULL will forward the message (via the
+callable VMS Mail interface) to GOATHUNTER.
+
+
+BULLETIN AND "From:" ADDRESSES
+------------------------------
+If you use the return address supplied by the MX SITE agent, the return address
+for BULLETIN messages will look something like the following:
+
+	From: MX%"@WKUVX1.BITNET:I-AMIGA@UBVM.BITNET"
+
+By default, MX_BULL_SITE_DELIVER.COM is set up to ignore the sender's address.
+If you want to use the MX SITE-supplied address, simply modify the following
+line in MX_BULL_SITE_DELIVER.COM:
+
+	$ USE_SITE_FROM = 0	!Change to 1 to use MX sender's address
+
+If the sender's address is ignored (again, the default), MX_BULL will search
+the RFC822 headers in the message for the "From:" line.  It then pulls out
+the sender's address in a format suitable for using the RESPOND command in
+BULLETIN.  This lets users easily RESPOND to the sender of a message, or
+POST a message to the list itself.
+
+Note: MX_BULL just uses the address it's given.  Some addresses are gatewayed
+to death, leaving a bad address on the "From:" line.  This frequently happens
+with messages coming via UUCP through Internet to Bitnet, etc.
+
+
+AUTHOR INFORMATION
+------------------
+MX_BULL was written by:
+
+	Hunter Goatley, VMS Systems Programmer, WKU
+
+	E-mail: goathunter@wkuvx1.bitnet
+	Voice:	502-745-5251
+
+	U.S. Mail:	Academic Computing, STH 226
+			Western Kentucky University
+			Bowling Green, KY 42101
+$eod 
+$copy/log sys$input MX_BULL_SITE_DELIVER.COM
+$deck
+$!
+$!  SITE_DELIVER.COM for MX_BULL
+$!
+$!  Author:	Hunter Goatley, goathunter@wkuvx1.bitnet
+$!  Date:	March 11, 1991
+$!
+$!  By default, MX_BULL will tell BULLETIN to search the RFC822 headers
+$!  in the message for a "Reply-to:" or "From:" line.  If you want MX_BULL
+$!  to use the P4 as the "From:" line, simply set USE_SITE_FROM to 1.
+$!
+$ USE_SITE_FROM = 0				!Change to 1 to use P4
+$ mxbull :== $mx_exe:mx_bull.exe
+$!
+$ set noon
+$ if f$trnlnm("SYS$SCRATCH").eqs."" then define SYS$SCRATCH MX_SITE_DIR:
+$ if USE_SITE_FROM				!Use P4 as "From:"?
+$ then	create mx_site_dir:sitesender.addr;	!If so, write it out to a file
+$	open/append tmp mx_site_dir:sitesender.addr;	!... to make sure DCL
+$	write tmp p4				!... doesn't mess it up
+$	close tmp				!...
+$	mxbull 'p2' 'p3' mx_site_dir:sitesender.addr
+$	delete/nolog mx_site_dir:sitesender.addr;
+$ else	mxbull 'p2' 'p3'			!Just let BULLETIN find "From:"
+$ endif
+$ exit 1	!Always return success
+$eod 
diff --git a/decus/vmslt00a/bulletin/news.txt b/decus/vmslt00a/bulletin/news.txt
new file mode 100755
index 0000000000000000000000000000000000000000..86274c1208adf4911dd2bb1b8e11021320233dd2
--- /dev/null
+++ b/decus/vmslt00a/bulletin/news.txt
@@ -0,0 +1,133 @@
+BULLETIN has the capability to read and post messages  to  USENET  NEWS  in  a
+client  mode.  I realize that there are many NEWS readers, some with much more
+elegant interfaces.  However, I elected to modify BULLETIN for  the  following
+reason:   We have many decnet nodes, but only several are internet nodes.  Our
+only access  to  a  news  server  was  via  internet.    In  order  for  those
+non-internet  nodes  to read USENET, the only method that seemed available was
+to run a NEWS server program on one of our own internet nodes so that it could
+be accessible via decnet.  I did not want to do that, as that requires storing
+the news groups on disk, and I do not have the room for that.   I  thus  added
+the  ability  in  BULLETIN  (actually  BULLCP) so that it acts as as a gateway
+between decnet and tcp for NEWS.  This method does not  require  spawning  any
+processes,  since the detached process BULLCP is always present, so the access
+is very fast.  Also, since BULLETIN uses a shared database to  store  info  on
+the  NEWS  groups and periodically updates it, there is no need for that to be
+done when a user accesses the NEWS groups.  Several other NEWS readers do this
+when you run them, which is why they take a long time to start up.  It is also
+possible to feed NEWS groups into  a  "real"  BULLETIN  folder,  so  that  the
+messages are saved on disk (see the file NEWS_TO_FOLDER.TXT). 
+
+Presently, BULLETIN can be used with  either  UCX,  MULTINET,  or  CMU  TCP/IP
+packages  (and of course DECNET) for reading NEWS.  Support for other packages
+can be added if I can find sites willing to beta test the  interface  for  me.
+The  source  for  the  TCP  interface  is in C rather than FORTRAN because the
+MULTINET include files are in C. However, if you do not have C, I will be glad
+to send the object for it (or to even possibly rewrite the code in FORTRAN). 
+
+The instructions for installation are as follows.  Define BULL_NEWS_SERVER  to
+be a system logical name pointing to either your internet or decnet NEWS node.
+If it is decnet, simply specify the decnet node name, i.e. 
+
+	$ DEFINE/SYSTEM BULL_NEWS_SERVER NERUS
+
+BULLETIN decides to use DECNET rather than TCP access based on the node  name.
+If it does not have any periods in it, then it assumes it is a DECNET node. 
+
+In our cluster, we usually have one node which is an internet  node,  and  the
+rest  non-internet  nodes.    If  you have a similar situation, you'll have to
+create a startup procedure that defines BULL_NEWS_SERVER to  be  the  internet
+news  server  address  only  on  the  node (or nodes) on the cluster that have
+actually internet access.  The other nodes will have BULL_NEWS_SERVER  defined
+as the decnet node name that BULLCP is running on in the cluster.  (Of course,
+BULLCP will have to be running on a node with internet access.)
+
+NOTE: If you want to disable the gateway feature, then before starting BULLCP,
+define the logical name: 
+
+	$ DEFINE/SYSTEM BULL_NO_NEWS_GATEWAY "TRUE"
+
+Defining this will only shut off the gateway.  BULLETIN will still be  allowed
+to read NEWS from the local node as long as BULL_NEWS_SERVER is defined. 
+
+You can also specify that BULLCP is only to act as a NEWS gateway.  This is to
+allow  adding the news gateway to an INTERNET site that you have DECNET access
+to, but which does not want to make use of any of the other BULLETIN features.
+You would specify the following command before starting BULLCP: 
+
+	$ DEFINE/SYSTEM BULL_NEWS_GATEWAY_ONLY "TRUE"
+
+It is also possible for BULLETIN to access news groups  that  are  located  on
+other  news  servers than the one specified by BULL_NEWS_SERVER.  This is done
+by creating the  file  BULL_DIR:BULL_ALT_NEWS.LIS  and  adding  a  line  which
+containsthe  name  of  the  news group and the news server where it's located.
+The format is news-group-name:news-server-name.
+
+In order to post messages, BULLETIN needs to know the internet nodename of the
+local host.  This is done automatically for nodes running MULTINET.  For other
+nodes, BULLETIN attempts to  translate  the  logical  name  ARPANET_HOST_NAME,
+INTERNET_HOST_NAME, and MX_NODE_NAME.  If you are on a DECNET node that is not
+on INTERNET (and is not part of a cluster which has an INTERNET address),  but
+you are accessing NEWS via DECNET, you can specify the hostname as follows: 
+
+     $ DEFINE/SYSTEM INTERNET_HOST_NAME "%localhost@internet-address"
+
+Where "localhost" is your local decnet hostname, and "internet-address" is the
+internet address of the gateway node. 
+
+The local time zone is detected by looking at  the  following  logical  names:
+LISP$TIME_ZONE,  MULTINET_TIMEZONE,  or  PMDF_TIMEZONE.    (LISP$TIME_ZONE  is
+defined if you have LISP installed.)
+
+The name of the organization is included in the header of  the  NEWS  message.
+This can be anything, but usually is the company or university name.  This can
+be hardcoded into the source by putting in BULLNEWS.INC, or  by  defining  the
+system logical name BULL_NEWS_ORGANIZATION. 
+
+The name of the mail protocol to use for responding by mail to  NEWS  messages
+can  also  be  either hardcoded by putting in BULLNEWS.INC, or by defining the
+system logical name BULL_NEWS_MAILER. 
+
+After installing the new BULLETIN, execute the command NEWS, which asks for  a
+list  of  all the news groups.  Because this is the first time it is executed,
+it will cause a load of all the remote news groups  into  a  local  data  base
+(BULL_DIR:BULLNEWS.DAT). This will take several minutes to do.  It is the only
+time that this load will be  done  interactively.    Afterwards,  BULLCP  will
+periodically  update  the data base.  For this reason, it is highly recommeded
+that BULLCP be installed. BULLCP will update NEWS every hour.  If you want  to
+change  this frequency, define the logical name BULL_NEWS_UPDATE to the number
+of minutes in between updates, i.e. DEFINE/SYSTEM BULL_NEWS_UPDATE "30" for 30
+minutes.    NOTE:  BULLCP  will create a subprocess BULLCP NEWS which does the
+update.  You can watch how long it takes for this to run in order to determine
+if you want to change the update period). 
+
+Due to long news group names recently created, you must do the following, or
+else those news groups will not be seen.  After BULLNEWS.DAT is created, do
+the following:
+
+$ ANAL/RMS/FDL/OUT=FIX.FDL BULL_DIR:BULLNEWS.DAT
+
+Edit FIX.FDL and find the first line which says
+	DUPLICATES no
+and change it to
+	DUPLICATES yes
+
+Then type:
+
+$ CONVERT BULL_DIR:BULLNEWS.DAT BULL_DIR:BULLNEWS.DAT/FDL=FIX.FDL
+
+Also, it is suggested that you run OPTIMIZE_RMS.COM on it, as it will cause the
+file to be compressed and will allow updates to run much faster (factor of 5 or
+more). 
+
+Never delete BULLNEWS.DAT.  There is no reason to ever  do  so,  and  it  will
+cause subscribed users to be subscribed to the wrong news groups. 
+
+WARNING: One user discovered that his server (using bnews?) had  a  bug  which
+caused  the updates to cause bogus "new messages" notifications for subscribed
+NEWS group when entering BULLETIN.    If  you  experience  this  problem,  try
+defining  the  system  logical name BULL_SPECIAL_NEWS_UPDATE.  This will cause
+the update to use a different algorithm which should  eliminate  the  problem,
+although it requires much more time to execute. 
+
+If you have any problems or questions, please let me know.
+									MRL
diff --git a/decus/vmslt00a/bulletin/news_to_folder.txt b/decus/vmslt00a/bulletin/news_to_folder.txt
new file mode 100755
index 0000000000000000000000000000000000000000..c100f0931d6a658c6f39538578fa9b3c64fadc50
--- /dev/null
+++ b/decus/vmslt00a/bulletin/news_to_folder.txt
@@ -0,0 +1,48 @@
+It is possible to automatically have messages from a news group be fed into  a
+real  folder, and visa versa.  This allows BULLETIN messages to be shared with
+a news group, thus giving access to such messages to people who  do  not  have
+access  to  BULLETIN.   This can also be combined with email access for people
+who have neither BULLETIN nor news group access. 
+
+To associate a folder with a news group, place the name of the news group into
+the  folder  description  surrounded  by  <>, i.e. <misc.test>.  It must be in
+lower case.  (Other text is allowed in the description, i.e. "THIS IS  A  TEST
+FOLDER  <misc.test>".)  When messages are added the folder, they are also sent
+to the news group, and new messages from the group are posted  to  the  folder
+(via  the  BULLCP  process  which wakes up on a periodic basis).  Whenever you
+modify the folder description and specify the news group  name,  you  will  be
+prompted  as  to  whether  you  want  to initializee the news group counter to
+either load all the messages present in the news group, or to load  only  news
+messages that appear there. 
+
+Messages posted to the news group from such a folder have a  special  line  in
+their  header  indicating  they were sent from that node using bulletin.  When
+bulletin feeds new postings back to the folder, it will see that  header  line
+and  also see that it was posted from that node, and thus will avoid adding it
+to the folder (and thus creating a duplicate message).  Note that messages are
+added  to  the  news  group  via  the  BULLCP process, so they will not appear
+immediately after being added to the folder. 
+
+If you are modifying an existing folder to make  it  associated  with  a  news
+group, and if you want to copy any existing messages in the folder to the news
+group, you can do that by using the command COPY/ORIGINAL/LOCAL and specifying
+the  news  group  as the destination.  /ORIGINAL will cause the original owner
+names and dates to be preserved (note, however, that dates older than 14  days
+in  the  past are not usually accepted by the news server, so dates older than
+that will be changed to the present date).  /LOCAL  will  create  the  special
+header  line in the messages to prevent BULLCP from adding those messages back
+to the folder from the news group.  /ALL can be  specified  to  copy  all  the
+messages in the folder. 
+
+If you create a remote folder that points to a folder that has  a  news  group
+associated  with  it,  you  do  not  have  to  specify  the  news group in the
+description of the remote node.  However, on the  node  on  which  the  folder
+actually  exists,  the  news  group  has be a stored news group, i.e. you must
+issue the command SET NEWS/STORED for that news group. 
+
+When a news group is specified for a folder, it is still possible to associate
+an  email  address  for  the messages to be sent to in the folder description.
+You do this by using [] to enclose the address rather than the usual <>,  i.e.
+[mrl@pfc.mit.edu]  See  help in BULLETIN on the command CREATE/DESCRIPTION for
+more info about associated email addresses.  Note that  these  features  allow
+you to create a full gateway between a news group and a mailing list. 
diff --git a/decus/vmslt00a/bulletin/nonsystem.txt b/decus/vmslt00a/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..f1f7d86296699f21a3ed0b944452230a6ccce18a
--- /dev/null
+++ b/decus/vmslt00a/bulletin/nonsystem.txt
@@ -0,0 +1,16 @@
+Non-system bulletins (such as this) can be submitted by any user.  Users are
+alerted at login time that new non-system bulletins have been added, but only
+their topics are listed.  Optionally, users can be prompted at login time to
+see if they wish to read the bulletins.  When reading the bulletins in this
+manner, the bulletins can optionally be written to a file.  If you have the
+subdirectory [.BULL] created, BULLETIN will use that directory as the default
+directory to write the file into.
+
+A user can disable this prompting featuring by using BULLETIN as follows: 
+
+$ BULLETIN
+BULLETIN> SET NOREADNEW
+BULLETIN> EXIT
+
+Afterwords, the user will only be alerted of the bulletins, and will have to
+use the BULLETIN utility in order to read the messages.
diff --git a/decus/vmslt00a/bulletin/optimize_rms.com b/decus/vmslt00a/bulletin/optimize_rms.com
new file mode 100755
index 0000000000000000000000000000000000000000..576fa3e106bdd1b01865b9bd84ac1e8d15a0c209
--- /dev/null
+++ b/decus/vmslt00a/bulletin/optimize_rms.com
@@ -0,0 +1,134 @@
+$ SET NOON
+$ EXIT_STATUS = 1
+$ IF P1 .NES. "" THEN GOTO BATCH
+$!
+$GET_FILE:
+$ INQUIRE P1 "File to be optimized (^Y to quit)"
+$!
+$ FILENAME = P1
+$ SPEC = F$SEARCH(FILENAME)
+$!
+$GOT_NAME_INTERACTIVE:
+$ NAME = F$PARSE(FILENAME,,,"NAME")
+$!
+$ IF F$FILE_ATTRIBUTE(FILENAME,"ORG") .EQS. "IDX" THEN-
+  GOTO INTERACTIVE_CHECK_ADDS
+$ WRITE SYS$OUTPUT "File not indexed"
+$ GOTO GET_FILE
+$INTERACTIVE_CHECK_ADDS:
+$ INQUIRE P2 "Number of records to add after initial load"
+$ IF P2 .EQS. "" THEN P2 = 0
+$!
+$ IF P2 .GE. 0 THEN GOTO INTERACTIVE_CHECK_CONVERT
+$ WRITE SYS$OUTPUT "Added records must be >= 0 "
+$ GOTO GOT_NAME_INTERACTIVE
+$!
+$INTERACTIVE_CHECK_CONVERT:
+$ INQUIRE P3 "Turn OFF Data and Key compression? (N)"
+$ INQUIRE P4 "Turn OFF Index compression? (N)"
+$!
+$ GOTO ADD_OK
+$!
+$BATCH:
+$GOT_NAME:
+$ FILENAME = P1
+$ SPEC = F$SEARCH(FILENAME)
+$!
+$ IF SPEC .NES. "" THEN GOTO FILE_EXISTS
+$ WRITE SYS$OUTPUT "File does not exist"
+$ EXIT_STATUS = %X18292
+$ GOTO DONE
+$!
+$FILE_EXISTS:
+$ NAME = F$PARSE(FILENAME,,,"NAME")
+$ IF F$FILE_ATTRIBUTE(FILENAME,"ORG") .EQS. "IDX" THEN-
+  GOTO TYPE_OK
+$ WRITE SYS$OUTPUT "File not indexed"
+$ EXIT_STATUS = 1000024
+$ GOTO DONE
+$!
+$TYPE_OK:
+$ IF P2 .EQS. "" THEN P2 = 0
+$ IF P2 .GE. 0 THEN GOTO ADD_OK
+$!
+$ WRITE SYS$OUTPUT "Added records must be >= 0 "
+$ EXIT_STATUS = %X38060
+$ GOTO DONE
+$!
+$ADD_OK:
+$ ADD_RECORDS = P2
+$!
+$ NUMBER_OF_KEYS == 'F$FILE_ATTRIBUTE(FILENAME,"NOK")
+$ TURN_DATA_COMPRESSION_OFF = P3
+$ TURN_INDEX_COMPRESSION_OFF = "Y"
+$ FDL_NAME = F$PARSE(".FDL;0",SPEC)
+$ TEMP_FILE = "''NAME'_TEMP_TEMP.COM"
+$ OPEN/WRITE/ERROR=OPEN_ERROR OUT 'TEMP_FILE
+$ WRITE OUT "$ DEFINE/USER SYS$COMMAND SYS$INPUT"
+$ WRITE OUT "$ ANALYZE/RMS/FDL/OUT=''FDL_NAME' ''FILENAME'"
+$ WRITE OUT "$ DEFINE/USER SYS$COMMAND SYS$INPUT"
+$ WRITE OUT "$ DEFINE/USER EDF$$PLAYBACK_INPUT KLUDGE"
+$ WRITE OUT "$ EDIT/FDL/SCRIPT=OPTIMIZE/ANALYZE=''FDL_NAME' ''FDL_NAME'"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT 'ADD_RECORDS
+$ IF ADD_RECORDS .EQ. 0 THEN GOTO SKIP_NON_ZERO
+$ WRITE OUT ""
+$ WRITE OUT ""
+$SKIP_NON_ZERO:
+$ WRITE OUT ""
+$ IF TURN_INDEX_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "IC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ IF TURN_DATA_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "RC"
+$  WRITE OUT "NO"
+$  WRITE OUT "KC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ WRITE OUT "FD"
+$ WRITE OUT "Created from OPTIMIZE_RMS.COM, WITH SPACE/BUCKETSIZE for" +-
+  " ''A DD_RECORDS' ADDED RECORDS"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$LOOP:
+$ IF NUMBER_OF_KEYS .EQ. 1 THEN GOTO CLOSE_FILE
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ IF TURN_INDEX_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "IC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ IF TURN_DATA_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "KC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ WRITE OUT "FD"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ NUMBER_OF_KEYS = 'NUMBER_OF_KEYS - 1
+$ GOTO LOOP
+$!
+$CLOSE_FILE:
+$ WRITE OUT "E"
+$ CLOSE OUT
+$!
+$ @'TEMP_FILE
+$ DELETE 'TEMP_FILE;*
+$ WRITE SYS$OUTPUT ""
+$ WRITE SYS$OUTPUT "Starting CONVERT of ''FILENAME'"
+$ CONVERT /NOSORT /STAT /FDL='FDL_NAME 'FILENAME 'FILENAME
+$ WRITE SYS$OUTPUT ""
+$ GOTO DONE
+$OPEN_ERROR:
+$ WRITE SYS$OUTPUT "Unable to open ''TEMP_FILE'"
+$DONE:
+$ EXIT 'EXIT_STATUS
diff --git a/decus/vmslt00a/bulletin/pmdf.com b/decus/vmslt00a/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..6a700ce4f7c07b9a3beb2251b1793c3f3cf5884b
--- /dev/null
+++ b/decus/vmslt00a/bulletin/pmdf.com
@@ -0,0 +1,4 @@
+$link/exe=pmdf_exe:bulletin_master.exe -
+    pmdf_exe:bulletin_master.obj/sysexe,pmdf_exe:pmdfshr_link.opt/opt, -
+    pmdf_com:ident.opt/opt,pmdf_exe:rmspro, -
+    bull.olb/lib,sys$share:vaxcrtl/lib
diff --git a/decus/vmslt00a/bulletin/pmdf.txt b/decus/vmslt00a/bulletin/pmdf.txt
new file mode 100755
index 0000000000000000000000000000000000000000..e3a40bca98bf9b0cc76a587007b97d5648dca474
--- /dev/null
+++ b/decus/vmslt00a/bulletin/pmdf.txt
@@ -0,0 +1,29 @@
+To allow PMDF to be able to transfer mail to BULLETIN folders, edit the file
+PMDF_TABLE:PMDF.CNF, and append the following 5 lines to the rewrite section
+(make sure you do not include any lines with spaces in that section.  Replace
+the string "urdomain", with your domain (i.e., my domain is PSFC.MIT.EDU).
+
+!
+! Rewrites for bulletin channel
+!
+BULLETIN             $U%BULLETIN@BULLETIN-DAEMON
+BULLETIN.urdomain    $U%BULLETIN@BULLETIN-DAEMON
+
+Then, add the following 5 lines to the channel section (or just put it at the
+end of that file).                    
+
+!
+! The BULLETIN Channel rule
+!
+bull_local single master slave_debug master_debug logging defragment charset7 us-ascii charset8 iso-8859-1
+BULLETIN-DAEMON
+
+After you do this, you can now link and install the BULLETIN executable using
+PMDF.COM  Once you do that, if you want email messages to be automatically
+transferred to a BULLETIN folder, you will need to add an alias to
+PMDF_TABLE:PMDF.CNF  For example, if you email sent to TEST to be placed in
+the TEST folder, you would add the line:
+
+test: test@bulletin  
+
+Note that folder names do not necessarily have to match account names.
diff --git a/decus/vmslt00a/bulletin/restart.com b/decus/vmslt00a/bulletin/restart.com
new file mode 100755
index 0000000000000000000000000000000000000000..71f7023963e7b796667f566c7ebdc319bb46a233
--- /dev/null
+++ b/decus/vmslt00a/bulletin/restart.com
@@ -0,0 +1,6 @@
+$ SET PROCESS/PRIVILEGE=ALL
+$ MCR SYSMAN
+SET ENV/CL
+SET PROF/PRIV=ALL
+DO DEASSIGN BULL_DISABLE/SYSTEM
+$ BULL/START
diff --git a/decus/vmslt00a/bulletin/setuser.mar b/decus/vmslt00a/bulletin/setuser.mar
new file mode 100755
index 0000000000000000000000000000000000000000..489f36fa37a2928fdfa6599c08a07c07b87e4c00
--- /dev/null
+++ b/decus/vmslt00a/bulletin/setuser.mar
@@ -0,0 +1,125 @@
+	.Title	SETUSER
+;
+;	Program Setuser
+;
+;	This program will change the username and UIC of the running process
+;
+;	To assemble:	$ MACRO SETUSER
+;			$ LINK SETUSER,SYS$SYSTEM:SYS.STB/SELECT
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+	$PCBDEF				;define PCB offsets
+	$JIBDEF				;define JIB offsets
+	$UAFDEF				;define user authorization file offsets
+INFAB:	$FAB	FAC=GET -		;only gets on input file
+		FNM=<SYSUAF> -		;SYSUAF may be defined as logical name
+		DNM=<SYS$SYSTEM:.DAT> -	;These are default directory & suffix
+		SHR=<PUT,GET,DEL,UPD>	;allow full sharing
+INRAB:	$RAB	FAB=INFAB -		;FAB for this RAB
+		KBF=COMMLD+8 -		;key value is typed in by user
+		KRF=0 -			;primary key
+		KSZ=12 -		;username is 12 bytes long
+		RAC=KEY -		;key access on this file
+		ROP=NLK -		;don't lock read records
+		UBF=BUFFER -		;address of buffer for I/O
+		USZ=2048		;size of buffer
+BUFFER:	.BLKB	2048			;buffer for data
+COMMLD:	.ASCID	/            /		;space for typed in username
+PROMPTD:.ASCID	/Username: /		;prompt string
+COMMLDS:.WORD	0			;space for number of bytes typed in
+FAODESC:.LONG	80
+	.LONG	FAOBUF
+FAOBUF:	.BLKB	80
+FAOLEN:	.BLKW	1
+	.BLKW	1
+FORSTR:	.ASCID	/PID:!XL from:[!OW,!OW] !AD to:[!OW,!OW] !AD/
+TT:	.ASCID	/SYS$OUTPUT/
+CHANTT:	.WORD	0			;space for terminal channel number
+IOSB:	.QUAD	0
+OLDUSER:.BLKB	12			;space for old username
+OLDUIC:	.BLKL	1			;space for old uic
+ERRORB:	JMP	ERROR			;for branch out of range
+
+JPIUSER:	.BLKB	12
+JPIUSER_LEN:	.BLKL	1
+
+	$DEFINI IT			;DEFINE ITEM LIST FOR GETJPI
+$DEF	ITL	.BLKW	1		;LENGTH OF OUTPUT BUFFER
+$DEF	ITM	.BLKW	1		;ITEM CODE (PROCESS NAME)
+$DEF	ITA	.BLKL	1		;ADDR OF OUTPUT BUFFER
+$DEF	ITAL	.BLKL	1		;ADDR OF WORD TO RECIEVE BYTES USED
+$DEF	ITEND	.BLKL	1		;ZERO LONG WORD TO END LIST
+$DEF	ITSIZE				;SIZE NEEDED FOR IT BLOCK
+	$DEFEND IT
+
+	.ENTRY	START,^M<>		;start of program
+	PUSHAW	COMMLDS			;address of word to get read byte count
+	PUSHAL	PROMPTD			;address of prompt string descriptor
+	PUSHAL	COMMLD			;address of descriptor to get command
+	CALLS	#3,G^LIB$GET_FOREIGN	;use run time library to get command
+	BLBC	R0,ERRORB		;low bit clear error
+	$OPEN	FAB=INFAB		;open file
+	BLBC	R0,ERRORB		;low bit clear error
+	$CONNECT RAB=INRAB		;connect file
+	BLBC	R0,ERRORB		;low bit clear error
+	$GET	RAB=INRAB		;read a record
+	CMPL	R0,#RMS$_RNF		;record not found?
+	BEQL	errorb			;that's all folks
+	CMPL	R0,#RMS$_NORMAL		;ok?
+	BNEQ	ERRORB			;no so quit
+
+	SUBL	#ITSIZE,SP		;GET SPACE FOR ITEM LIST
+	MOVL	SP,R2			;POINT TO IT
+	MOVW	#12,ITL(R2)		;SET UP ITEM LIST
+	MOVW	#JPI$_USERNAME,ITM(R2)
+	MOVAB	JPIUSER,ITA(R2)
+	MOVAW	JPIUSER_LEN,ITAL(R2)
+	CLRL	ITEND(R2)
+	$GETJPI_S	ITMLST=(R2)	;GET PROCESS NAME
+	ADDL	#ITSIZE,SP		;RESTORE STACK POINTER
+
+	MOVL	INRAB+RAB$L_RBF,R7	;put address of read record in R7
+	MOVL	UAF$L_UIC(R7),R8	;R8 has UIC we want
+	$CMKRNL_S TWEAK			;change mode to kernel to tweak UIC
+					;and username
+	BLBC	R0,ERROR		;low bit clear error
+	ADDL3	#UAF$S_USERNAME,R7,R8
+	ADDL3	#UAF$T_USERNAME,R7,R9
+	$FAO_S	CTRSTR=FORSTR,-		;format string
+		OUTBUF=FAODESC,-	;char descript for formatted output
+		OUTLEN=FAOLEN,-		;long word to hold length of output
+		P1=R9,-			;PID
+		P2=OLDUIC+2,-		;old UIC, group number
+		P3=OLDUIC,-		;old UIC, member number
+		P4=#12,-		;usernames are 12 bytes
+		P5=#OLDUSER,-		;address of old username
+		P6=UAF$L_UIC+2(R7),-	;UIC, group number
+		P7=UAF$L_UIC(R7),-	;UIC, member number
+		P8=R8,-			;usernames are 12 bytes
+		P9=R9			;address of username
+	BLBC	R0,ERROR		;low bit clear error
+	MOVL	FAOLEN,FAODESC
+	PUSHAL	FAODESC			;address of descriptor to get command
+	CALLS	#1,G^LIB$PUT_OUTPUT	;use run time library to get command
+	BLBC	R0,ERROR		;low bit clear error
+EXIT:
+	$CLOSE	FAB=INFAB -		;close file
+		ERR=ERROR
+ERROR:	$EXIT_S	R0			;exit with error if any
+	.ENTRY	TWEAK,^M<>		;beginning of kernel mode code
+	MOVL	@#CTL$GL_PCB,R11	;put address of our PCB in R11
+	MOVL	PCB$L_PID(R11),R9	;save PID
+	MOVL	PCB$L_UIC(R11),OLDUIC	;save old UIC
+	MOVL	R8,PCB$L_UIC(R11)	;change our UIC
+	MOVL	PCB$L_JIB(R11),R10	;put address of Job Info Block in R10
+					;MOVC blats R0-R5
+	MOVC3	#12,JIB$T_USERNAME(R10),OLDUSER ;save old username
+	CMPC3	JPIUSER_LEN,JPIUSER,OLDUSER
+	BEQL	GOOD
+	CLRL	R0
+	RET	
+GOOD:	MOVC3	#12,UAF$T_USERNAME(R7),JIB$T_USERNAME(R10) ;change username JIB
+	MOVC3	#12,UAF$T_USERNAME(R7),CTL$T_USERNAME ;change username in P1
+EEXIT:	MOVL	#SS$_NORMAL,R0		;set normal exit status
+	RET				;end of exec mode code
+	.END	START			;end of program
diff --git a/decus/vmslt00a/bulletin/update.fil b/decus/vmslt00a/bulletin/update.fil
new file mode 100755
index 0000000000000000000000000000000000000000..6f20f13eec116bddfb35f9c7b11d82975d95386c
--- /dev/null
+++ b/decus/vmslt00a/bulletin/update.fil
@@ -0,0 +1,11 @@
+$ if p1 .nes. "" then FS 'P1'
+$ COPY 'FM' [MRL.BULLETIN.SEND]/LOG
+$ COPY 'FM' CMODA::IR:[BULLETIN]/LOG
+$ TAB2SP 'FM' 
+$ RENAME 'FM' [MRL.NET]
+$ PUR [MRL.BULLETIN.SEND]'FM'
+$ PUR [MRL.NET]'FM'
+$ IF FM .EQS. "CHMAIL.MAI" THEN P3 = "AAAREADME."
+$ IF P2 .EQS. "" THEN COPY 'FM' [ANONYMOUS.BULLETIN]'P3'
+$ IF P3 .EQS. "" THEN PUR [ANONYMOUS.BULLETIN]'FM'
+$ IF P3 .NES. "" THEN PUR [ANONYMOUS.BULLETIN]'p3'
diff --git a/decus/vmslt00a/bulletin/upgrade.com b/decus/vmslt00a/bulletin/upgrade.com
new file mode 100755
index 0000000000000000000000000000000000000000..b91fa7ce7837d054cd932fc7901c1c782153454b
--- /dev/null
+++ b/decus/vmslt00a/bulletin/upgrade.com
@@ -0,0 +1,53 @@
+$!
+$!  Normally, new versions of BULLETIN don't require any special
+$!  installation except to link and install the new executable (and
+$!  possibly relink PMDF or MX interfaces if any changes affect them).
+$!  However, when there is a change to the data file format, you should run
+$!  the following procedure.         
+$!
+$!  This is a sample upgrade procedure.  You will have to modify references
+$!  to the directory where the new executables are stored, which are marked
+$!  with ***. You will also have to change the references to the procedures
+$!  that link either PMDF or MX.  These procedures usually replace the old
+$!  executable, but that should not be done until BULLETIN has been disabled
+$!  (by defining the logical name BULL_DISABLE).  If you run this procedure
+$!  with a parameter (i.e. @UPGRADE LINK), it will call those linking
+$!  procedures. Alternatively, you could define BULL_DISABLE and run those
+$!  procedures manually.  Or, you could change them so they don't replace the
+$!  old procedures and run them manually, and simply have this procedure
+$!  replace them.  Whatever you find more convenient.
+$!  
+$!  This procedure should be run on all stand alone nodes or boot nodes of
+$!  clusters on which bulletin is installed. After running upgrade.com, run
+$!  restart.com to restart bulletin.  If you don't make use of remote
+$!  folders, you can run restart.com immediately after upgrade.com rather
+$!  than waiting to install the new version on all nodes.  Otherwise, you
+$!  should try to run this procedure simultaneously on all clusters and then
+$!  wait until it finishes on all nodes before running restart.com. 
+$!  Otherwise, remote folder access attempts will fail.                 
+$!  
+$ SET PROCESS/PRIVILEGE=ALL
+$ COPY ALCVAX::USER1:[MRL.BULLETIN]BULLETIN.EXE BULL_DIR:              ! *** 
+$ COPY ALCVAX::USER1:[MRL.BULLETIN]BULL.HLB SITE$ROOT:[SYSHLP]         ! *** 
+$ PMDF = F$TRNLNM("PMDF_ROOT")
+$ MX = F$TRNLNM("MX_EXE")
+$ BULL/STOP
+$ IF PMDF .NES. "" THEN PMDF = F$SEARCH("PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE")
+$ IF PMDF .NES. "" THEN DELETE/NOCONFIRM PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE;*
+$ IF MX .NES. "" THEN MX = F$SEARCH("MX_EXE:MX_BULL.EXE")
+$ IF MX .NES. "" THEN DELETE/NOCONFIRM MX_EXE:MX_BULL.EXE;*
+$ MCR SYSMAN
+SET ENV/CL
+SET PROF/PRIV=ALL
+DO DEFINE BULL_DISABLE/SYSTEM "DISABLE"
+DO MCR INSTALL BULL_DIR:BULLETIN/REPLACE
+$ IF P1 .NES. "" .AND. PMDF .NES. "" THEN @USER1:[MRL.BULLETIN]LINK_PMDF ! ***
+$ IF P1 .NES. "" .AND. MX .NES. "" THEN @USER1:[MRL.BULLETIN]LINK_MX	 ! ***
+$ DEFINE BULL_DISABLE "ENABLE"		! Enable it just for this process.
+$ BULLETIN
+$ IF F$TRNLNM("BULL_NEWS_SERVER") .NES. "" THEN BULLETIN MISC.TEST
+$ IF PMDF .NES. "" THEN-
+   COPY ALCVAX::PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE PMDF_ROOT:[EXE]	! ***
+$ IF MX .NES. "" THEN-
+   COPY ALCVAX::MX_EXE:MX_BULL.EXE MX_EXE:                 		! ***
+$ DEASSIGN BULL_DISABLE
diff --git a/decus/vmslt00a/bulletin/writemsg.txt b/decus/vmslt00a/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..2bfabfdabc8b43294194358412f5464016f9de3f
--- /dev/null
+++ b/decus/vmslt00a/bulletin/writemsg.txt
@@ -0,0 +1,36 @@
+BULLETIN contains subroutines for writing a message directly to a folder.  This
+would be useful for someone who is using the BBOARD feature, but wants to avoid
+the extra overhead of having the message sent to an account as MAIL, and then
+have BULLCP read the mail.  It is better if the network mail could be written
+directly to the folder bypassing VMS MAIL, as it reduces a lot of cpu overhead.
+
+Call INIT_MESSAGE_ADD to initiate a message addition.
+Call WRITE_MESSAGE_LINE to write individual message lines.
+Call FINISH_MESSAGE_ADD to complete a message addition.
+
+Calling formats:
+
+	CALL INIT_MESSAGE_ADD(IN_FOLDER,IN_FROM,IN_DESCRIP,IER)
+C
+C  INPUTS:
+C	IN_FOLDER  - Character string containing folder name
+C	IN_FROM	   - Character string containing name of owner of message.
+C		     If empty, the default is the owner of the process.
+C	IN_DESCRIP - Character string containing subject of message.
+C		     If empty, the message is searched for a line
+C		     which starts with "Subj:" or "Subject:".
+C  OUTPUTS:
+C	IER - Error status.  True if properly connected to folder.
+C		False if folder not found.
+C
+
+	CALL WRITE_MESSAGE_LINE(BUFFER)
+C
+C  INPUTS:
+C	BUFFER - Character string containing line to be put into message.
+C
+
+	CALL FINISH_MESSAGE_ADD
+C
+C  NOTE:  Only should be run if INIT_MESSAGE_ADD was successful.
+C
diff --git a/decus/vmslt02a/bulletin/aaareadme.txt b/decus/vmslt02a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..f45613c8983cbcef9f12b71e18407fe6589e95b8
Binary files /dev/null and b/decus/vmslt02a/bulletin/aaareadme.txt differ
diff --git a/decus/vmslt97a/bulletin/aaareadme.1st b/decus/vmslt97a/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..e3d297e202bd916e66b2326de901482ce4fb8859
Binary files /dev/null and b/decus/vmslt97a/bulletin/aaareadme.1st differ
diff --git a/decus/vmslt97a/bulletin/aaareadme.txt b/decus/vmslt97a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..b6ab799473bc5be07df693680ba1eed600c7a3dc
Binary files /dev/null and b/decus/vmslt97a/bulletin/aaareadme.txt differ
diff --git a/decus/vmslt97a/bulletin/bulletin.ann b/decus/vmslt97a/bulletin/bulletin.ann
new file mode 100755
index 0000000000000000000000000000000000000000..c374df5f7ec7342c35ff63963cbac1b403452c9b
--- /dev/null
+++ b/decus/vmslt97a/bulletin/bulletin.ann
@@ -0,0 +1,26 @@
+Article 168253 of comp.os.vms:
+BULLETIN is a bulletin board utility which I wrote for VMS.  However,  because
+many  of  our VAX users moved to PCs and MACs, they have wanted access to read
+and post to the BULLETIN folders.  In the past I accomplished this  via  EMAIL
+and  used  the  feature  which  allowed  mail to be sent to and from a folder.
+However, some people have asked for Web access.  In order  to  easily  provide
+this  feature  without  a  lot of work, we decided to do the following:  Since
+news server software is now easily  and  cheapily  available,  and  most  news
+readers  (i.e. Netscape) have the ability to read usenet news groups from more
+than one news server, I set up a local  news  server  to  serve  private  news
+groups.   I then modified BULLETIN to allow a folder with email access to also
+have the ability to post and receive to a specified news group.  I also had to
+modify BULLETIN to allow it to access more than one news server.  Thus, a user
+can now post and read the same folder either via either  BULLETIN,  EMAIL,  or
+WEB access via a newsgroup. 
+
+The new version of BULLETIN (v2.3) which has this  feature  is  available  via
+anonymous ftp to PSFC.MIT.EDU in the BULLETIN sub-directory. 
+
+Note:  The newsgroup-folder feature had existed in the past but would not work
+with  email.  It also was crude in that if you added a message, it would first
+post the message to the newsgroup and then later be added to the folder.    It
+now is added immediately to the folder.  Sharp users will note that this gives
+BULLETIN the ability to be used as a newsgroup to mailing list gateway. 
+
+
diff --git a/decus/vmslt97a/bulletin/handout.txt b/decus/vmslt97a/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vmslt97a/bulletin/handout.txt differ
diff --git a/decus/vmslt97a/bulletin/instruct.txt b/decus/vmslt97a/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vmslt97a/bulletin/instruct.txt differ
diff --git a/decus/vmslt98a/bulletin/aaareadme.doc b/decus/vmslt98a/bulletin/aaareadme.doc
new file mode 100755
index 0000000000000000000000000000000000000000..a6e90eba4c286b88dfe5f2c1db51c338b2dc7dcf
--- /dev/null
+++ b/decus/vmslt98a/bulletin/aaareadme.doc
@@ -0,0 +1,201 @@
+The following are instructions for creating and installing the BULLETIN
+utility. None of the command procedures included here are sophisticated, so it
+is likely that several modifications will have to be made by the installer.
+The installer should enable all privileges before installation.
+
+Once installation is complete, it is suggested that the installer enter
+BULLETIN and read HELP FOLDERS to see the options available when creating
+or modifying folders.  BULLETIN creates a default folder called GENERAL
+which is a SYSTEM folder (allows messages to be posted which are displayed
+in full when people login.)  This folder can be modified (name changed,
+SYSTEM setting removed, etc.), but it will remain the default folder
+which is selected when BULLETIN is entered, and it cannot be deleted.
+
+One of the main uses of BULLETIN, besides storage of messages that are manually
+entered by users, is storage of messages from network mailing lists.  This is
+done by using the BBOARD feature, which is enabled using the SET BBOARD command
+inside BULLETIN.  The alternative method is for mail messages to be written
+directly by a mailing program by calling internal BULLETIN routines.  Such a
+a program has been written for the popular mail utilities PMDF and MX.  If you
+wish to do so for another utility, read the text file WRITEMSG.TXT.  I would be
+glad to include any such programs with my distribution if you think such a
+program would be of use to other users.
+
+Responding to mail which is added via the BBOARD feature is done using
+VMS MAIL.  The name of the mail protocol to use for responding by mail
+can be either hardcoded by putting in BULLNEWS.INC, or by defining the
+system logical name BULL_NEWS_MAILER, i.e. DEFINE BULL_NEWS_MAILER "MX%".
+
+If for some reason this is inappropriate, you can define BULL_MAILER
+to point to a command procedure, and which will be run instead of VMS MAIL.
+The parameters passed to this procedure are P1 = username and P2 = subject.
+
+1) CREATE.COM
+   This will compile and link the BULLETIN sources. Also, there are several
+   INCLUDE files for the fortran sources (.INC files). BULLETIN will create it's
+   data files in the directory pointed to by the logical name BULL_DIR.  If you
+   elect not to use this definition, BULLFILES.INC should be modified.
+   Note that after this procedure compiles the sources, it puts the objects
+   into an object library, and then deletes all the OBJ files in the directory.
+
+   CREATE.COM will automatically determine if you are running on an alpha
+   rather than a vax and will issue the appropriate commands for that cpu.
+   Of course, separate executables are needed for the two cpus, so if your 
+   site has both, you will have to run this procedure separately on each.
+
+   NOTE 1: If you plan on using the USENET NEWS reader capability of BULLETIN,
+   read NEWS.TXT for installation instructions before compiling.
+
+   NOTE 2: The maximum number of folders for this distribution is 96 folders.
+   If you wish to increase this, modify BULLUSER.INC and recompile the sources.
+   When the new executable is run, it will create a new BULLUSER.DAT data file
+   and rename the old one to BULLUSER.OLD.  You cannot reduce the number of
+   folders.
+
+2) INSTALL.COM
+   The following procedure copies the executable image to BULL_DIR and
+   installs it with certain privileges.  It also installs the necessary
+   help files in SYS$HELP.  (BULLETIN help file is installed into the
+   system help library HELPLIB.HLB.  If you don't wish this done, delete
+   or modify the appropriate line in the procedure.  Also, the help
+   library for the BULLETIN program, BULL.HLB, can be moved to a different
+   directory other than SYS$HELP.  If this is done, the system logical name
+   BULL_HELP should be defined to be the directory where the library is
+   to be found.)
+
+3) LOGIN.COM
+   This contains the commands that should be executed at login time
+   by SYS$MANAGER:SYLOGIN.COM.  It defines the BULLETIN commands.
+   It also executes the command BULLETIN/LOGIN in order to notify
+   the user of new messages.  NOTE: If you wish the utility to be a
+   different name than BULLETIN, you should modify this procedure.
+   The prompt which the utility uses is named after image executable.
+   If you want messages displayed upon logging in starting from
+   oldest to newest (rather than newest to oldest), add /REVERSE to
+   the BULLETIN/LOGIN command.  Note that users with the DISMAIL
+   flag setting in the authorization file will not be notified of
+   new messages.  See help on the SET LOGIN command within the BULLETIN
+   utility for more information on this.  Also, please note that when
+   a brand new user to the system logins, to avoid overwhelming the new
+   user with lots of messages, only PERMANENT SYSTEM messages are displayed.
+
+   If you want SYSTEM messages, i.e. messages which are displayed in full
+   when logging in, to be continually displayed for a period of time rather
+   than just once, you should add the /SYSTEM= qualifier.  This is documented
+   in BULLETIN.HLP, although there it is referred to only with respect to
+   a user wanting to review system messages.  It can be added with /LOGIN.
+
+   DECWINDOWS users should note the following: Both SYLOGIN and LOGIN are
+   executed twice, once before the terminal is actually created, while
+   SYS$OUTPUT is still a mailbox, the other time after the terminal is
+   created.  To avoid this, place the following code in both procedure. 
+   It causes them to execute only when the output is a terminal. This code
+   also helps to allow programs to be placed in LOGIN.COM that prompt for
+   terminal input.  BULLETIN does this if you select READNEW mode for
+   displaying messages when logging in, as READNEW mode will ask you if
+   you want to display the messages text.  Attempts to read terminal input
+   under DECWINDOWS when SYS$OUTPUT is still a mailbox will cause DECTERM
+   creation to fail.  (This problem is fixed under MOTIF).
+
+   $ IF F$LOCATE("_TW",F$GETJPI("","PRCNAM")) .NE. 0 THEN GOTO START
+   $ IF "''F$MODE()'" .NES. "INTERACTIVE" THEN GOTO START
+   $ IF F$GETDVI("SYS$OUTPUT","TRM") THEN GOTO START
+   $ GOTO FINISH
+   $START:
+   .
+   .
+   body of SYLOGIN.COM (including BULLETIN command)
+   .
+   .
+   $FINISH:
+   $ EXIT
+
+4) BULLSTART.COM
+   This procedure contains the commands that should be executed after
+   a system startup.  It should be executed by SYS$MANAGER:SYSTARTUP.COM.
+   It installs the BULLETIN utility with correct privileges.  It also
+   includes the command BULLETIN/STARTUP.  This starts up a detached process
+   with the name BULLCP.  It periodically checks for expire messages,cleanups
+   empty space in files, and converts BBOARD mail to messages.  It also allows
+   other DECNET nodes to share it's folders.  If you don't want this feature
+   and don't plan on having multiple folders or make use of BBOARD, you could
+   eliminate this command if you like.  However, it is highly recommended that
+   you create this process to avoid extra overhead when users login.  NOTE:
+   BULLCP normally is created so it is owned by the DECNET account.  If that
+   account does not exist, BULLCP will be owned by the account that issues
+   the BULLETIN/START command.  In that case, access via other DECNET nodes
+   will not be available.
+
+   If you are installing BULLETIN on a cluster and plan to have the bulletin
+   files be shared between all of the cluster nodes, you only need to have
+   this process running on one node. On all other nodes, the system logical
+   name BULL_BULLCP should be defined (to anything you want) so as to notify
+   BULLETIN that BULLCP is running. (On the local node where BULLCP is running,
+   this logical name is automatically defined.)
+
+   The system logical name BULL_CUSTOM can be defined to enable several 
+   features.  It is equated to a hex number string.  
+	Bit 0 set = need privileges to create folder.
+	    1 set = captive account can write files.
+	    2 set = captive account can use editor. 
+   
+   If you want to have more than one database, you can do so by redefining 
+   BULL_DIR to another directory.  However, only directories that are 
+   defined in the list of equivalence names pointed to by the system logical 
+   name BULL_DIR_LIST are allowed.  For example:
+
+	DEFINE/SYSTEM BULL_DIR_LIST SITE$ROOT:[SYSEXE],USER1:[MRL]
+
+   Then BULL_DIR can be defined as SITE$ROOT:[SYSEXE] or USER1:[MRL].  
+   BULL_DIR_LIST must be defined on all nodes in a cluster.
+   
+   The use of the MARK command to mark messages require that a file be
+   created for each user which saves the marked info.  That file file is
+   stored in the directory pointed to by the logical name BULL_MARK.  You can
+   either let users who want to use this command define it themselves, or
+   you can define it for them, i.e. DEFINE/SYSTEM BULL_MARK SYS$LOGIN.
+
+5) INSTRUCT.COM
+   This procedure adds 2 permanent messages which give a very brief
+   description about the BULLETIN utility, and how to turn off optional
+   prompting of non-system messages (via SET NOREADNEW).
+
+6) BOARD_SPECIAL.COM
+   This command procedure describes and illustrates how to use the
+   SET BBOARD/SPECIAL feature.  This feature allows the use of BBOARD
+   where the input does not come from VMS MAIL.  For example, this could
+   be used in the case where mail from a non-DEC network is not stored
+   in the VMS MAIL.  Another example is BOARD_DIGEST.COM.  This file
+   takes mail messages from "digest" type mailing lists and splits them
+   into separate BULLETIN messages for easier reading.
+
+   To use this feature, place the special command procedure into the
+   bulletin file directory using the name BOARD_SPECIAL.COM.  If you want
+   to have several different special procedure, you should name the command
+   procedure after the username specified by the SET BBOARD command.
+
+7) UPGRADE.COM
+   This procedure is used to upgrade to a new version of BULLETIN.
+   See comments for instructions.
+
+8) MASTER.COM
+   If you are using PMDF, and want to use the BBOARD option, a set of
+   routines are included which will allow PMDF to write message directly
+   into folders, which is a much more effecient way of doing it than
+   the normal BBOARD method of using VMS MAIL.  Read PMDF.TXT for how
+   to do this.
+
+9) OPTIMIZE_RMS.COM
+   This routine optimizes index files.  To run, type @OPTIMIZE_RMS.COM
+   followed by the filename.  If you omit the filename, it will prompt
+   you to allow you to turn off or on several different types of RMS
+   compression.  The default is to turn on all types of compression.
+   The optimization will cause the file to be compressed.
+
+   If you use the NEWS feature, it is suggest that you run this procedure
+   on BULLNEWS.DAT after it is created.  Compressing that file greatly speeds
+   up the NEWS update process.  If you are tight on space, and have been
+   running BULLETIN for a long time, it might also be useful to compress
+   BULLINF.DAT if that file is very large.  However, compressing that (or
+   the other BULLETIN data files) don't appear to save any execution time,
+   unlike BULLNEWS.DAT.
diff --git a/decus/vmslt98a/bulletin/aaareadme.txt b/decus/vmslt98a/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..bb9a4a014711620889216b66f3caf0a8289f0b76
Binary files /dev/null and b/decus/vmslt98a/bulletin/aaareadme.txt differ
diff --git a/decus/vmslt98a/bulletin/allmacs.mar b/decus/vmslt98a/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..3725b8ad2b7e36926f562ac80706e31797db99ae
--- /dev/null
+++ b/decus/vmslt98a/bulletin/allmacs.mar
@@ -0,0 +1,312 @@
+;
+;  Name: SETACC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the account name of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETACC(account)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	account		- Character string containing account name
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETACC
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+
+	.PSECT	 DATA,NOEXE
+
+NEWACC:	.BLKB	12				; Contains new account name
+;
+;  Executable:
+;
+	.PSECT	CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETACC,^M<R2,R3,R4,R5,R6,R7>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R6				; Get number of arguments
+	CMPL	R6,#1				; Correct number of arguments?
+	BNEQ	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#8,NEWACC		; Get new account name string
+	$CMKRNL_S ROUTIN=SETACC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY	SETACC_C,^M<R2,R3,R4,R5,R6>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R6			; Address of current process
+	MOVL	PCB$L_JIB(R6),R6		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R6		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#8,NEWACC,JIB$T_ACCOUNT(R6) 	; change account JIB
+	MOVC3	#8,NEWACC,CTL$T_ACCOUNT 	; change account in P1
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUIC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: May 31, 1983
+;
+;  Purpose: To set the UIC of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUIC(group number, user number)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	group number	- longword containing UIC group number
+;	user number	- longword containing UIC user number
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUIC	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+
+	.PSECT	 SETUIC_DATA,NOEXE
+
+UIC:	.BLKL	1
+;
+;  Executable:
+;
+	.PSECT	SETUIC_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY SETUIC,^M<R2,R3>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R2				; Get number of arguments
+	CMPL	R2,#2				; Are there 2 arguments
+	BNEQ	5$				; If not, return
+	MOVL	@4(AP),R3			; Group number into R3
+	ROTL	#16,R3,R3			; Move to upper half of R3
+	ADDL2	@8(AP),R3			; User number to top half of R3
+	MOVL	R3,UIC
+	$CMKRNL_S ROUTIN=SETUIC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY SETUIC_C,^M<R4>			; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R2			; Address of current process
+	MOVL	UIC,PCB$L_UIC(R2)		; Set UIC to specified
+;	MOVL	UIC,PCB$L_UIC(R4)		; Set UIC to specified
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUSER.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the Username of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUSER(username)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	username	- Character string containing username
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUSER	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+	.PSECT	 SETUSER_DATA,NOEXE
+
+NEWUSE:	.BLKB	12				; Contains new username
+OLDUSE: .BLKB	12				; Contains old username
+OLDLEN: .BLKW   1
+;
+;  Executable:
+;
+	.PSECT	SETUSER_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETUSER,^M<R2,R3,R4,R5,R6,R7,R8>        
+	CLRL	R0				; 0 is error code 
+	MOVZBL	(AP),R8				; Get number of arguments
+	CMPL	R8,#1				; Correct number of arguments
+	BLSS	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,NEWUSE		; Get new username string
+	CMPL	R8,#2				; Old username given?
+	BLSS	2$				; No
+	MOVZBL	@8(AP),R6			; Get size of string
+	MOVL	8(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,OLDUSE		; Get old username string
+        MOVL	R6,OLDLEN
+	$CMKRNL_S ROUTIN=SETUSER_C2		; Must run in kernel mode
+	TSTL	R0				; If old username is checks with
+   	BEQL	2$				; present process name, change
+	MOVL	#2,R0				; to new username, else flag
+	RET					; error and return
+2$:	$CMKRNL_S ROUTIN=SETUSER_C1		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY  SETUSER_C1,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#12,NEWUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	MOVC3	#12,NEWUSE,CTL$T_USERNAME 	; change username in P1    
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+
+	.ENTRY  SETUSER_C2,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: CMPC destroys r0-r5
+	CMPC	OLDLEN,OLDUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	RET
+
+	.SBTTL	KMODE error handler
+
+; This error handler should prevent those embarrasing crashes when you woof
+; in kernel mode.  It doesn't try to fix anything, it just unwinds the stack
+; and saves the error signal status.  Good for little things like division
+; by zero or access violations etc.  If you destroy an important system data
+; structure this handler wont be able to fix it and the system will eventually
+; crash.
+;
+; Written by Anthony C. McCracken, Northern Arizona University.
+; 25-SEP-1992
+;
+; I was tired of rebooting the machine after silly coding errors.  :)
+;
+	.ENTRY	KMODE_EHAND,^M<R5,R6>
+	MOVL	4(AP),R5		; Get the signal array
+	CMPL	4(R5),#SS$_UNWIND
+	BNEQ	10$			; Just return if were already
+	RET				; unwinding
+10$:	MOVL	8(AP),R6		; Get the mechanism array
+	MOVL	4(R5),12(R6)		; Stash the error code
+	$UNWIND_S			; and unwind back out
+	RET
+
+
+	.TITLE	READ_HEADER - Read Image Header
+	.IDENT	/1-001/
+
+; This subroutine returns the image identification and link time.
+;
+; Format:
+;
+;   status.wlc.v = READ_HEADER( ident.wt.ds [,time.wt.ds] )
+;
+; Parameters:
+;
+;   ident	The image identification text.
+;
+;   time	The image link time (text format).
+
+
+;   Date	By		Comments
+;  4/10/87	D.E. Greenwood	Originally written by John Miano, 24-June-1986 -
+;				obtained from April 87 DECUS L&T Sig Newsletter
+	.LIBRARY	"SYS$LIBRARY:LIB"
+
+	$DSCDEF
+	$IHDDEF
+	$IHIDEF
+	$SSDEF
+
+; Argument pointer offsets
+
+	$OFFSET 4,POSITIVE,<IDENT,TIME>
+
+	.PSECT READ_HEADER, RD, NOWRT, EXE, LONG
+	.ENTRY READ_HEADER, ^M< R2, R3, R4, R5, R6, R7, R8, R11 >
+
+	CMPL	(AP),#1 		; Make sure that there is at least
+	BGEQ	ENOUGH_ARGUMENTS	;  one argument to this routine
+	MOVL	#SS$_INSFARG, R0
+	RET
+
+ENOUGH_ARGUMENTS:
+
+; Get the identification of the image.
+
+	MOVL	@#CTL$GL_IMGHDRBF, R11	; R11 - Address of image buffer
+	MOVL	(R11), R6		; R6  - Address of image header
+
+	CVTWL	IHD$W_IMGIDOFF(R6), R7
+	MOVAB	(R6)[R7], R7		; R7 - Address of ID Block
+
+	CVTBL	IHI$T_IMGID(R7),R0	; Length of the ID string
+	MOVL	IDENT(AP), R8
+	MOVC5	R0, <IHI$T_IMGID+1>(R7), #32, -
+		DSC$W_LENGTH(R8), @DSC$A_POINTER(R8)
+
+	CMPL	(AP), #2
+	BGEQ	RETURN_TIME
+	MOVZBL	#1, R0
+	RET
+
+RETURN_TIME:
+
+; Get the time the image was linked and convert it to ASCII
+
+	$ASCTIM_S -
+		TIMBUF=@TIME(AP), -
+		TIMADR=IHI$Q_LINKTIME(R7)
+
+	RET
+
+.END
diff --git a/decus/vmslt98a/bulletin/allmacs_axp.mar b/decus/vmslt98a/bulletin/allmacs_axp.mar
new file mode 100755
index 0000000000000000000000000000000000000000..fb06e99cfeb522d26fb3c7c7f2b53d485d896958
--- /dev/null
+++ b/decus/vmslt98a/bulletin/allmacs_axp.mar
@@ -0,0 +1,312 @@
+;
+;  Name: SETACC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the account name of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETACC(account)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	account		- Character string containing account name
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETACC
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+
+	.PSECT	 DATA,NOEXE
+
+NEWACC:	.BLKB	12				; Contains new account name
+;
+;  Executable:
+;
+	.PSECT	CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETACC,^M<R2,R3,R4,R5,R6,R7>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R6				; Get number of arguments
+	CMPL	R6,#1				; Correct number of arguments?
+	BNEQ	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#8,NEWACC		; Get new account name string
+	$CMKRNL_S ROUTIN=SETACC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY	SETACC_C,^M<R2,R3,R4,R5,R6>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R6			; Address of current process
+	MOVL	PCB$L_JIB(R6),R6		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R6		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#8,NEWACC,JIB$T_ACCOUNT(R6) 	; change account JIB
+	MOVC3	#8,NEWACC,CTL$T_ACCOUNT 	; change account in P1
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUIC.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: May 31, 1983
+;
+;  Purpose: To set the UIC of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUIC(group number, user number)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	group number	- longword containing UIC group number
+;	user number	- longword containing UIC user number
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUIC	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+
+	.PSECT	 SETUIC_DATA,NOEXE
+
+UIC:	.BLKL	1
+;
+;  Executable:
+;
+	.PSECT	SETUIC_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY SETUIC,^M<R2,R3>
+	CLRL	R0				; 0 is error code
+	MOVZBL	(AP),R2				; Get number of arguments
+	CMPL	R2,#2				; Are there 2 arguments
+	BNEQ	5$				; If not, return
+	MOVL	@4(AP),R3			; Group number into R3
+	ROTL	#16,R3,R3			; Move to upper half of R3
+	ADDL2	@8(AP),R3			; User number to top half of R3
+	MOVL	R3,UIC
+	$CMKRNL_S ROUTIN=SETUIC_C		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY SETUIC_C,^M<R4>			; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R2			; Address of current process
+	MOVL	UIC,PCB$L_UIC(R2)		; Set UIC to specified
+;	MOVL	UIC,PCB$L_UIC(R4)		; Set UIC to specified
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+;
+;  Name: SETUSER.MAR
+;
+;  Type: Integer*4 Function (MACRO)
+;
+;  Author: M. R. London
+;
+;  Date: Jan 26, 1983
+;
+;  Purpose: To set the Username of the current process (which turns out
+;	to be the process running this program.)
+;
+;  Usage:
+;	status = SETUSER(username)
+;
+;	status		- $CMKRNL status return. 0 if arguments wrong.
+;	username	- Character string containing username
+;
+;  NOTES:
+;	Must link with SS:SYS.STB
+;
+
+	.Title SETUSER	Set uic
+	.IDENT /830531/
+;
+;  Libraries:
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+;
+;  Global variables:
+;
+	$PCBDEF
+	$JIBDEF
+;
+;  local variables:
+;
+	.PSECT	 SETUSER_DATA,NOEXE
+
+NEWUSE:	.BLKB	12				; Contains new username
+OLDUSE: .BLKB	12				; Contains old username
+OLDLEN: .BLKW   1
+;
+;  Executable:
+;
+	.PSECT	SETUSER_CODE,EXE,NOWRT	; Executable code
+
+	.ENTRY	SETUSER,^M<R2,R3,R4,R5,R6,R7,R8>        
+	CLRL	R0				; 0 is error code 
+	MOVZBL	(AP),R8				; Get number of arguments
+	CMPL	R8,#1				; Correct number of arguments
+	BLSS	5$				; If not, return
+	MOVZBL	@4(AP),R6			; Get size of string
+	MOVL	4(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,NEWUSE		; Get new username string
+	CMPL	R8,#2				; Old username given?
+	BLSS	2$				; No
+	MOVZBL	@8(AP),R6			; Get size of string
+	MOVL	8(AP),R7			; Get address of descriptor
+	MOVL	4(R7),R7			; Get address of string
+	MOVC5	R6,(R7),#32,#12,OLDUSE		; Get old username string
+        MOVL	R6,OLDLEN
+	$CMKRNL_S ROUTIN=SETUSER_C2		; Must run in kernel mode
+	TSTL	R0				; If old username is checks with
+   	BEQL	2$				; present process name, change
+	MOVL	#2,R0				; to new username, else flag
+	RET					; error and return
+2$:	$CMKRNL_S ROUTIN=SETUSER_C1		; Must run in kernel mode
+5$:	RET
+
+	.ENTRY  SETUSER_C1,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: MOVC destroys r0-r5
+	MOVC3	#12,NEWUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	MOVC3	#12,NEWUSE,CTL$T_USERNAME 	; change username in P1    
+	MOVZWL	#SS$_NORMAL,R0			; Normal ending
+	RET
+
+	.ENTRY  SETUSER_C2,^M<R2,R3,R4,R5,R7>	; Entry mask
+	MOVAB	KMODE_EHAND,(FP)		; Exception handler
+	MOVL	@#CTL$GL_PCB,R7			; Address of current process
+	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
+;	MOVL	PCB$L_JIB(R4),R7		; Address of Job Info Block
+						; NOTE: CMPC destroys r0-r5
+	CMPC	OLDLEN,OLDUSE,JIB$T_USERNAME(R7) 	; change username JIB
+	RET
+
+	.SBTTL	KMODE error handler
+
+; This error handler should prevent those embarrasing crashes when you woof
+; in kernel mode.  It doesn't try to fix anything, it just unwinds the stack
+; and saves the error signal status.  Good for little things like division
+; by zero or access violations etc.  If you destroy an important system data
+; structure this handler wont be able to fix it and the system will eventually
+; crash.
+;
+; Written by Anthony C. McCracken, Northern Arizona University.
+; 25-SEP-1992
+;
+; I was tired of rebooting the machine after silly coding errors.  :)
+;
+	.ENTRY	KMODE_EHAND,^M<R5,R6>
+	MOVL	4(AP),R5		; Get the signal array
+	CMPL	4(R5),#SS$_UNWIND
+	BNEQ	10$			; Just return if were already
+	RET				; unwinding
+10$:	MOVL	8(AP),R6		; Get the mechanism array
+	MOVL	4(R5),12(R6)		; Stash the error code
+	$UNWIND_S			; and unwind back out
+	RET
+
+
+	.TITLE	READ_HEADER - Read Image Header
+	.IDENT	/1-001/
+
+; This subroutine returns the image identification and link time.
+;
+; Format:
+;
+;   status.wlc.v = READ_HEADER( ident.wt.ds [,time.wt.ds] )
+;
+; Parameters:
+;
+;   ident	The image identification text.
+;
+;   time	The image link time (text format).
+
+
+;   Date	By		Comments
+;  4/10/87	D.E. Greenwood	Originally written by John Miano, 24-June-1986 -
+;				obtained from April 87 DECUS L&T Sig Newsletter
+	.LIBRARY	"SYS$LIBRARY:LIB"
+
+	$DSCDEF
+	$EIHDDEF
+	$EIHIDEF
+	$SSDEF
+
+; Argument pointer offsets
+
+	$OFFSET 4,POSITIVE,<IDENT,TIME>
+
+	.PSECT READ_HEADER, RD, NOWRT, EXE, LONG
+	.ENTRY READ_HEADER, ^M< R2, R3, R4, R5, R6, R7, R8, R11 >
+
+	CMPL	(AP),#1 		; Make sure that there is at least
+	BGEQ	ENOUGH_ARGUMENTS	;  one argument to this routine
+	MOVL	#SS$_INSFARG, R0
+	RET
+
+ENOUGH_ARGUMENTS:
+
+; Get the identification of the image.
+
+	MOVL	@#CTL$GL_IMGHDRBF, R11	; R11 - Address of image buffer
+	MOVL	(R11), R6		; R6  - Address of image header
+
+	MOVL	EIHD$L_IMGIDOFF(R6), R7
+	MOVAB	(R6)[R7], R7		; R7 - Address of ID Block
+
+	CVTBL	EIHI$T_IMGID(R7),R0	; Length of the ID string
+	MOVL	IDENT(AP), R8
+	MOVC5	R0, <EIHI$T_IMGID+1>(R7), #32, -
+		DSC$W_LENGTH(R8), @DSC$A_POINTER(R8)
+
+	CMPL	(AP), #2
+	BGEQ	RETURN_TIME
+	MOVZBL	#1, R0
+	RET
+
+RETURN_TIME:
+
+; Get the time the image was linked and convert it to ASCII
+
+	$ASCTIM_S -
+		TIMBUF=@TIME(AP), -
+		TIMADR=EIHI$Q_LINKTIME(R7)
+
+	RET
+
+.END
diff --git a/decus/vmslt98a/bulletin/bad.for b/decus/vmslt98a/bulletin/bad.for
new file mode 100755
index 0000000000000000000000000000000000000000..37d9d2626510e8afa637b35d4a0f42cb8ad78ed9
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bad.for
@@ -0,0 +1,22 @@
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	OPEN (UNIT=5,FILE='BULLNEWS.DAT',STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER,
+     &          57:64:CHARACTER:DESCENDING))
+	BULLNEWS_FILE  = 'BULL_DIR:BULLNEWS.DAT'
+	CALL OPEN_BULLNEWS_SHARED       ! Open folder file
+
+	DO WHILE (IER.EQ.0)
+		CALL READ_FOLDER_FILE_TEMP(IER)
+              	IF (IER.EQ.0) WRITE (5,IOSTAT=IER) NEWS_FOLDER1_COM
+	END DO
+
+	TYPE *,FOLDER1
+	END
diff --git a/decus/vmslt98a/bulletin/board_digest.com b/decus/vmslt98a/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..dec53c189229960499c10127241c1cd8cebb2239
--- /dev/null
+++ b/decus/vmslt98a/bulletin/board_digest.com
@@ -0,0 +1,77 @@
+$!
+$! BOARD_DIGEST.COM
+$!
+$! Command file invoked by folder associated with a BBOARD which is
+$! is specified with /SPECIAL.  It will convert "digest" mail and
+$! split it into separate messages.  This type of mail is used in
+$! certain Arpanet mailing lists, such as TEXHAX and INFO-MAC.
+$!
+$ FF[0,8] = 12			! Define a form feed character
+$ SET PROTECT=(W:RWED)/DEFAULT
+$ SET PROC/PRIV=SYSPRV
+$ USER := 'F$GETJPI("","USERNAME")
+$ EXTRACT_FILE = "BULL_DIR:" + "''USER'" + ".TXT"
+$ DEFINE/USER EXTRACT_FILE BULL_DIR:'USER'
+$ MAIL
+READ
+EXTRACT EXTRACT_FILE
+DELETE
+$ OPEN/READ INPUT 'EXTRACT_FILE'
+$ OPEN/WRITE OUTPUT 'EXTRACT_FILE'
+$ READ INPUT FROM_USER
+$AGAIN:
+$ READ/END=ERROR INPUT BUFFER
+$ IF F$EXTRACT(0,3,BUFFER) .NES. "To:" THEN GOTO SKIP
+$ USER = F$EXTRACT(4,F$LEN(BUFFER),BUFFER)
+$ GOTO AGAIN1
+$SKIP:
+$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN
+$AGAIN1:
+$ READ/END=ERROR INPUT BUFFER
+$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN1
+$ FROM = " "
+$ SUBJ = " "
+$NEXT:
+$ READ/END=EXIT INPUT BUFFER
+$FROM:
+$ IF F$EXTRACT(0,5,BUFFER) .NES. "From:" THEN GOTO SUBJECT
+$ FROM = BUFFER 
+$ GOTO NEXT
+$SUBJECT:
+$ IF F$EXTRACT(0,8,BUFFER) .NES. "Subject:" THEN GOTO NEXT
+$ SUBJ = BUFFER - "Subject:"
+$F2:
+$ IF F$LENGTH(SUBJ) .EQ. 0 THEN GOTO WRITE
+$ IF F$EXTRACT(0,1,SUBJ) .NES. " " THEN GOTO WRITE
+$ SUBJ = F$EXTRACT(1,F$LENGTH(SUBJ),SUBJ)
+$ GOTO F2
+$WRITE:
+$ WRITE OUTPUT FROM_USER
+				! Write From: + TAB + USERNAME
+$ WRITE OUTPUT "To:	" + USER
+				! Write To: + TAB + BBOARDUSERNAME
+$ WRITE OUTPUT "Subj:	" + SUBJ
+				! Write Subject: + TAB + mail subject
+$ WRITE OUTPUT ""		! Write one blank line
+$ IF FROM .NES. " " THEN WRITE OUTPUT FROM
+$READ:
+$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
+$ IF F$EXTRACT(0,15,BUFFER) .EQS. "---------------" THEN GOTO READ1
+$ WRITE OUTPUT BUFFER
+$ GOTO READ
+$READ1:
+$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
+$ IF F$LOCATE(":",BUFFER) .EQ. F$LENGTH(BUFFER) THEN GOTO READ1
+$ WRITE OUTPUT FF
+$ FROM = " "
+$ SUBJ = " "
+$ GOTO FROM
+$EXIT:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ PUR 'EXTRACT_FILE'
+$ EXIT
+$ERROR:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ DELETE 'EXTRACT_FILE';
diff --git a/decus/vmslt98a/bulletin/board_special.com b/decus/vmslt98a/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..93e16c3d9c42b59f57f99ca6e5e454e1ea380cec
--- /dev/null
+++ b/decus/vmslt98a/bulletin/board_special.com
@@ -0,0 +1,108 @@
+$!
+$! BOARD_SPECIAL.COM
+$!
+$! Command file invoked by folder associated with a BBOARD which is
+$! is specified with /SPECIAL.  This can be used to convert data to
+$! a message via a different means than the VMS mail.  This is done by
+$! converting the data to look like output created by the MAIL utility,
+$! which appears as follows:
+$!
+$!	First line is 0 length line.
+$!	Second line is "From:" followed by TAB followed by incoming username
+$!	Third line is "To:" followed by TAB followed by BBOARD username
+$!	Fourth line is "Subj:" followed by TAB followed by subject
+$!	The message text then follows.
+$!	Message is ended by a line containing a FORM FEED.
+$!
+$! This command file should be put in the BBOARD_DIRECTORY as specified
+$! in BULLFILES.INC.  You can also have several different types of special
+$! procedures.  To accomplish this, rename the file to the BBOARD username.
+$! i.e. if you specify SET BBOARD FOO/SPECIAL, you could name the file
+$! FOO.COM and it will execute that rather than BOARD_SPECIAL.COM.
+$!
+$! The following routine is the one we use to convert mail from a non-DEC
+$! mail network.  The output from this mail is written into a file which
+$! is slightly different from the type outputted by MAIL.
+$!
+$! (NOTE: A username in the SET BBOARD command need only be specified if
+$! the process which reads the mail requires that the process be owned by
+$! a specific user, which is the case for this sample, and for that matter
+$! when reading VMS MAIL.  If this is not required, you do not have to
+$! specify a username.)
+$!
+$ USERNAME := 'F$GETJPI("","USERNAME")'		! This trims trailing spaces
+$ IF F$SEARCH("MFE_TELL_FILES:"+USERNAME+".MAI") .EQS. "" THEN EXIT
+$ SET DEFAULT BULL_DIR:	! BULLETIN looks for text in BBOARD directory
+$ SET PROTECT=(W:RWED)/DEFAULT
+$ IF F$SEARCH("MFEMSG.MAI") .NES. "" THEN -
+  DELETE MFEMSG.MAI;*		! Delete any leftover output files.
+$ MSG := $MFE_TELL: MESSAGE
+$ DEFINE/USER SYS$COMMAND SYS$INPUT
+$ MSG				! Read MFENET mail
+copy * MFEMSG
+delete *
+exit
+$ FF[0,8] = 12			! Define a form feed character
+$ OPEN/READ/ERROR=EXIT INPUT MFEMSG.MAI
+$ OUTNAME = USERNAME+".TXT"	! Output file will be 'USERNAME'.TXT
+$ OPEN/WRITE OUTPUT 'OUTNAME'
+$ READ/END=END INPUT DATA		! Skip first line in MSG output
+$HEADER:
+$ FROM = ""
+$ SUBJ = ""
+$ MFEMAIL = "T"
+$NEXTHEADER:
+$ IF (FROM.NES."") .AND. (SUBJ.NES."") THEN GOTO SKIPHEADER
+$ READ/END=END INPUT DATA		! Read header line in MSG output
+$ IF DATA .EQS. "" THEN GOTO SKIPHEADER	! Missing From or Subj ??
+$ IF FROM .NES. "" THEN GOTO SKIPFROM
+$ IF F$LOCATE("From: ",DATA) .NES. 0 THEN GOTO 10$
+$ MFEMAIL = "F"
+$ FROM= F$EXTRACT(6,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$10$:
+$ IF F$LOCATE("Reply-to: ",DATA) .NES. 0 THEN GOTO 20$
+$ MFEMAIL = "F"
+$ FROM= F$EXTRACT(10,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$20$:
+$ IF F$LOCATE("From ",DATA) .NES. 0 THEN GOTO SKIPFROM
+$ FROM= F$EXTRACT(5,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$SKIPFROM:
+$ IF SUBJ .NES. "" THEN GOTO SKIPSUBJ
+$ IF F$LOCATE("Subject",DATA) .NES. 0 THEN GOTO SKIPSUBJ
+$ SUBJ= F$EXTRACT(F$LOCATE(": ",DATA)+2,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$SKIPSUBJ:
+$ GOTO NEXTHEADER
+$SKIPHEADER:
+$ WRITE OUTPUT "From:	" + FROM
+				! Write From: + TAB + USERNAME
+$ WRITE OUTPUT "To:	" + USERNAME
+				! Write To: + TAB + BBOARDUSERNAME
+$ WRITE OUTPUT "Subj:	" + SUBJ
+				! Write Subject: + TAB + mail subject
+$ WRITE OUTPUT ""		! Write one blank line
+$ IF (DATA.EQS."") .OR. MFEMAIL THEN GOTO SKIPBLANKS
+$50$:
+$ READ/END=END INPUT DATA		! Skip rest of main header
+$ IF DATA .NES. "" THEN GOTO 50$
+$60$:
+$ READ/END=END INPUT DATA		! Skip all of secondary header
+$ IF DATA .NES. "" THEN GOTO 60$
+$SKIPBLANKS:
+$ READ/END=END INPUT DATA		! Skip all blanks
+$ IF DATA .EQS. "" THEN GOTO SKIPBLANKS
+$NEXT:				! Read and write message text
+$ WRITE OUTPUT DATA
+$ IF DATA .EQS. FF THEN GOTO HEADER
+			! Multiple messages are seperated by form feeds
+$ READ/END=END INPUT DATA
+$ GOTO NEXT
+$END:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ DELETE MFEMSG.MAI;
+$EXIT:
+$ EXIT
diff --git a/decus/vmslt98a/bulletin/bull_news.c b/decus/vmslt98a/bulletin/bull_news.c
new file mode 100755
index 0000000000000000000000000000000000000000..437ad44f8fdb0cc0225f4e2accc7cb7052865615
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bull_news.c
@@ -0,0 +1,705 @@
+#include <string.h>
+#include <descrip.h>
+#include <stdio.h>
+#include "sys$library:iodef.h"
+
+#if MULTINET
+
+#include "multinet_root:[multinet.include.sys]types.h"
+#include "multinet_root:[multinet.include.sys]socket.h"
+#include "multinet_root:[multinet.include.netinet]in.h"
+#include "multinet_root:[multinet.include.arpa]inet.h"
+#include "multinet_root:[multinet.include]netdb.h"
+#include "multinet_root:[multinet.include]errno.h"
+#include "multinet_root:[multinet.include.vms]inetiodef.h"
+
+static char inet[7] = "INET0:";
+$DESCRIPTOR(inet_d,inet);
+
+static struct dns {
+	unsigned char function;
+	unsigned char call_code;
+	short zeros;
+	short length;
+	char string[512];
+} buf1, buf2;
+
+struct  sockaddr_un {
+        short   sun_family;             /* AF_UNIX */
+        char    sun_path[109];          /* path name (gag) */
+};
+#else
+
+#if UCX
+
+#include <ucx$inetdef.h>
+
+struct sockaddr {
+  short inet_family;
+  short inet_port;
+  int inet_adrs;
+  char bklb[8];
+  };
+
+struct itlist { int lgth; struct sockaddr *hst; };
+
+static short sck_parm[2];
+static struct sockaddr local_host, remote_host;
+struct itlist lhst_adrs, rhst_adrs;
+
+static char ucxdev[11] = "UCX$DEVICE";
+$DESCRIPTOR(ucxdev_d,ucxdev);
+
+static int addr_buff;
+
+#define htons(x) ((unsigned short)((x<<8)|(x>>8)))
+
+#else
+
+#if TWG
+
+#include <types.h>
+#include <socket.h>
+#include <netdb.h>
+#include <in.h>
+#include <inetiodef.h>
+
+static char inet[6] = "INET:";
+$DESCRIPTOR(inet_d,inet);
+
+#else
+
+#define CMU 1
+static char ip[4] = "IP:";
+$DESCRIPTOR(ip_d,ip);
+
+#endif
+
+#endif
+
+#endif
+
+static char task[20];
+$DESCRIPTOR(task_d,task);
+
+static int s;
+
+static struct iosb {
+	short status;
+	short size;
+	int info;
+} iosb;
+
+#define TCP 0
+#define DECNET 1
+
+static int mode = TCP;
+
+#if MULTINET
+
+#include <lib$routines>
+#include <stdarg.h>
+#ifdef __ALPHA
+unsigned int __VA_COUNT_BUILTIN(void);
+#define va_count(count)		(count = __VA_COUNT_BUILTIN())
+#else
+#ifdef VAXC
+#define va_count(n) vaxc$va_count(&n)
+extern int vaxc$va_count();
+#else
+#define va_count(n) decc$va_count(&n)
+extern int decc$va_count();
+#endif
+#endif
+
+static int FindRoutine(struct dsc$descriptor *image,
+		       struct dsc$descriptor *routine, int (**rtn)());
+
+int inet_ntoa1(int *arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"inet_ntoa");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = *arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int gethostname1(int arg1,int arg2)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"gethostname");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int htons1(int arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"htons");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int gethostbyname1(int arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"gethostbyname");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+static int FindRoutine(struct dsc$descriptor *image,
+		       struct dsc$descriptor *routine, int (**rtn)())
+{
+  lib$establish(lib$sig_to_ret);
+  return lib$find_image_symbol(image,routine,rtn);
+}
+#endif
+
+news_get_chan()
+{return(s);}
+
+news_set_chan(i)
+int *i;
+{s = *i;}
+
+news_disconnect()
+{
+#if UCX
+	sys$cancel(s);
+	sys$qiow(0,s,IO$_DEACCESS,0,0,0,0,0,0,0,0,0);
+#endif
+	sys$dassgn(s);
+}
+
+#if MULTINET || TWG
+
+static struct hostent *hp;
+static struct sockaddr_in sin;
+
+#endif
+
+int *node;
+
+news_gethost()
+{
+	/*
+	 *  Get the IP address of the NEWS host.
+	 *  As of MULTINET 3.0, cannot be done at AST level
+	 *  so can't do in NEWS_ASSIGN(), as BULLCP calls it at
+	 *  AST level if the decnet gateway feature is used.
+	 */
+#if TWG
+	struct hostent *gethostbyname();
+#else
+#if MULTINET
+#endif
+#endif
+
+	node = getenv("BULL_NEWS_SERVER");
+	if (!node) return(0);
+	if (!strchr(node,'.')) return(1); 
+
+#if TWG
+	hp = gethostbyname(node);
+#else
+#if MULTINET
+	hp = gethostbyname1(node);
+#endif
+#endif
+	return(1);
+}
+
+news_assign()
+{
+	int n;
+
+	if (!strchr(node,'.')) {
+	   strcpy(&task[0],node);
+	   n = strlen(node);
+	   strcpy(&task[n],"::\"TASK=NNTP\"");
+	   task_d.dsc$w_length = 13 + n;
+	   if (!(sys$assign(&task_d,&s,0,0) & 1)) return(0);
+	   mode = DECNET;
+	   return(1);
+	}
+#if MULTINET || TWG
+	/*
+	 *  Create a "sockaddr_in" structure which describes the remote
+	 *  IP address we want to send to (from gethostbyname()).
+	 */
+
+        if (!hp) {
+          int h[4],i;
+          if (sscanf(node,"%d.%d.%d.%d",&h[0],&h[1],&h[2],&h[3]) == 4) {
+            for (i=0;i<4;i++) if (h[i] < 0 || h[i] > 255) return(0);
+	    sin.sin_addr.s_addr = (h[3]<<24)+(h[2]<<16)+(h[1]<<8)+(h[0]);
+	  } else
+	    return(0);
+	  sin.sin_family = AF_INET;
+	}
+        else {
+ 	  sin.sin_family = hp->h_addrtype;
+	  memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
+        }
+#if TWG
+	sin.sin_port = htons(119);
+#else
+	sin.sin_port = htons1(119);
+#endif
+
+	/*
+	 *  Create an IP-family socket on which to make the connection
+	 */
+
+	if (!(sys$assign(&inet_d,&s,0,0) & 1)) return(0);
+#else
+#if UCX
+         if (!(sys$assign(&ucxdev_d,&s,0,0) & 1)) return(0);
+	{
+           short retlen;
+	   struct dsc$descriptor host_name
+		= {strlen(node),DSC$K_CLASS_S,DSC$K_DTYPE_T,node};
+	   int comm = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYNAME;
+	   struct dsc$descriptor command
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&comm};
+	   struct dsc$descriptor host_ad
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&addr_buff};
+	   struct iosb nam_iosb;
+
+           if (!(sys$qiow(0,s,IO$_ACPCONTROL,&nam_iosb,0,0,
+                       &command,&host_name,&retlen,&host_ad,0,0) & 1)
+               || !(nam_iosb.status & 1)) {
+              sys$dassgn(s);
+	      return(0);
+	   }
+	}
+#else
+	if (!(sys$assign(&ip_d,&s,0,0) & 1)) return(0);
+#endif
+#endif
+	return(1);
+}
+
+struct iosb accept_iosb;
+
+nntp_listen(listen_chan)
+int *listen_chan;
+{
+#if MULTINET
+	struct sockaddr_in sin;
+	struct iosb accept_iosb;
+
+	if (!(sys$assign(&inet_d,listen_chan,0,0) & 1)) return(0);
+
+	/*
+	 *  Create an IP-family socket on which to listen for connections
+	 */
+	if (!(sys$qiow(0,*listen_chan,IO$_SOCKET,&accept_iosb,0,0,AF_INET,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	/*
+	 *  Create a "sockaddr_in" structure which describes the port we
+	 *  want to listen to. Address INADDR_ANY means we will accept
+	 *  connections to any of our local IP addresses.
+	 */
+
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = INADDR_ANY;
+	sin.sin_port = htons1(119);
+
+	/*
+	 *  Bind to that address...
+	 */
+
+	if (!(sys$qiow(0,*listen_chan,IO$_BIND,&accept_iosb,0,0,
+	   &sin,sizeof(sin),0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+ 	/*
+	 *  Declare to the kernel that we want to listen for connections
+	 *  on this port, and that the kernel may queue up to five such
+	 *  connections for us.
+	 */
+
+	if (!(sys$qiow(0,*listen_chan,IO$_LISTEN,&accept_iosb,0,0,5,
+	    0,0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	return(1);
+#else
+	return(0);
+#endif
+}
+
+nntp_accept_wait(listen_chan,listen_ast,listen_iosb)
+int *listen_chan,*listen_ast,*listen_iosb;
+{
+#if MULTINET                                            
+	if (!(sys$qio(0,*listen_chan,IO$_ACCEPT_WAIT,listen_iosb,listen_ast,
+	    0,0,0,0,0,0,0) & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	return(1);
+#endif
+}
+ 
+nntp_accept(listen_chan,accept_chan,accept_iosb)
+int *listen_chan,*accept_chan;
+struct iosb *accept_iosb;
+{
+#if MULTINET
+	struct sockaddr_in sin;
+	FILE *fp;
+	char buf[128];
+	char *cp, *h;
+	int s;
+	struct sockaddr_un sun = {AF_UNIX};
+
+	*accept_chan = -1;
+
+	    /*
+	     *	Call accept to accept a new connection. This 'peels'
+	     *	a connection off of the original socket and returns to us
+	     *	a new channel to the connection. We could now close
+	     *	down the original socket if we didn't want to handle
+	     *	more connections.
+	     */
+	if (!(sys$assign(&inet_d,accept_chan,0,0) & 1)) return(0);
+
+	if (!(sys$qiow(0,*accept_chan,IO$_ACCEPT,accept_iosb,0,0,
+	   &sin,sizeof(sin),*listen_chan,0,0,0) & 1)
+	   || !(accept_iosb->status & 1)) return(0);
+
+	fp = fopen("BULL_TCP_NEWS_GATEWAY", "r");
+	if (!fp) return(1);
+
+	/* A non-official way of getting ip name at ast level */
+
+	if (!(sys$assign(&inet_d,&s,0,0) & 1)) return(0);
+	if (!(sys$qiow(0,s,IO$_SOCKET,&iosb,0,0,AF_UNIX,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1))
+	    {printf("1 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	strcpy(sun.sun_path,"DNS");
+	if (!(sys$qiow(0,s,IO$_CONNECT,&iosb,0,0,&sun,sizeof(sun),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("2 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+/*	buf1.function = 1;	/* gethostbyname */
+	buf1.function = 2;	/* gethostbyaddr */
+	buf1.call_code = 0;
+	buf1.length = strlen(inet_ntoa1((int)(&sin.sin_addr)));
+ 	strcpy(buf1.string,inet_ntoa1((int)(&sin.sin_addr)));
+
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,&buf1,
+					sizeof(buf1),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("3 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	if (!(sys$qiow(0,s,IO$_READVBLK,&iosb,0,0,&buf2,
+					sizeof(buf2),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("4 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	printf("5 iosb.status = %d\n",iosb.status);sys$dassgn(s);
+	buf2.string[buf2.length] = 0;
+	for (cp=buf2.string; *cp; cp++) *cp = tolower(*cp);
+
+	while (fgets(buf, sizeof(buf), fp)) {
+	    for (cp=buf; *cp != '\n'; cp++) *cp = tolower(*cp);
+	    *cp = 0;
+	    for (cp=buf; *cp == ' ' || *cp == '\t'; cp++);
+	    if (*cp == '\n' || *cp == '#') continue;
+	    if (!strcmp(buf2.string,cp)) return (1);
+	    if (*cp == '.' && strstr(buf2.string,cp)) return (1);
+	}
+	(void) fclose(fp);
+
+	return (0);
+#endif
+}
+
+news_socket()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qiow(0,s,IO$_SOCKET,&iosb,0,0,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qiow(0,s,IO$_SETMODE,&iosb,0,0,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+
+	return(1);
+}
+
+news_socket_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qio(*efn,s,IO$_SOCKET,biosb,astadr,*astprm,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) ) return(0);
+#else
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qio(0,s,IO$_SETMODE,biosb,astadr,*astprm,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) ) return(0);
+#else
+	return(-1);
+#endif
+#endif
+
+	return(1);
+}
+
+news_create()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qiow(0,s,IO$_CONNECT,&iosb,0,0,&sin,sizeof(sin),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+#if UCX 
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qiow(0,s,IO$_ACCESS,&iosb,0,0,0,0,&rhst_adrs,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+	if (!(sys$qiow(0,s,IO$_CREATE,&iosb,0,0,node,119,0,1,0,300) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#endif
+
+	return(1);
+}
+
+news_create_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qio(*efn,s,IO$_CONNECT,biosb,astadr
+		,*astprm,&sin,sizeof(sin),0,0,0,0) & 1)) return(0);
+#else
+#if UCX
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qio(*efn,s,IO$_ACCESS,biosb,astadr,*astprm,0,
+		0,&rhst_adrs,0,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_CREATE,biosb,astadr,*astprm,node,
+		119,0,1,0,300) & 1))
+	   return(0);
+#endif
+#endif
+
+	return(1);
+}
+
+news_connect()
+{
+	if (!news_gethost()) return(0);
+	if (!news_assign()) return(0);
+	if (!news_socket()) return(0);
+	return(news_create());
+}
+
+news_write_packet(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+#if CMU
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,!mode,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#else
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_write_packet_bullcp(efn,biosb,astadr,astprm,buf,len)
+int *biosb,*astadr,*astprm,*efn,*buf,*len;
+{
+#if CMU
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,!mode,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,0,0,0) & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_read_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+	if (!(sys$qiow(0,s,IO$_READVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+	n = iosb.size;
+
+	return(n);
+}
+
+news_gethostname(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	if (mode == DECNET) return (-1);
+#if TWG
+	return(gethostname(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+#if MULTINET
+	return(gethostname1(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+	return(-1);
+#endif
+#endif
+}
diff --git a/decus/vmslt98a/bulletin/bull_newsdummy.for b/decus/vmslt98a/bulletin/bull_newsdummy.for
new file mode 100755
index 0000000000000000000000000000000000000000..8637998f87fccc31238f44a78ef55ff75f20a6ad
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bull_newsdummy.for
@@ -0,0 +1,99 @@
+	INTEGER FUNCTION NEWS_ASSIGN()
+
+	NEWS_ASSIGN = 0
+
+	RETURN
+	END
+
+	INTEGER FUNCTION NEWS_GET_CHAN(I)
+
+	NEWS_GET_CHAN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWS_SET_CHAN(I)
+
+	RETURN
+	END
+
+	INTEGER FUNCTION NEWS_SOCKET_BULLCP(I,J,K,L)
+
+	NEWS_SOCKET_BULLCP = 0
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION NEWS_CREATE_BULLCP(I,J,K,L)
+
+	NEWS_CREATE_BULLCP = 0
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION NEWS_WRITE_PACKET_BULLCP(I,J,K,L,M,N)
+
+	NEWS_WRITE_PACKET_BULLCP = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWS_DISCONNECT
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_CONNECT
+
+	NEWS_CONNECT = .FALSE.
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_WRITE_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_WRITE_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_READ_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_READ_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_GETHOSTNAME(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_GETHOSTNAME = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_GETHOST()
+
+	NEWS_GETHOST = 0
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bullcom.cld b/decus/vmslt98a/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..d6461edb0958550f351ae940612f94a8fd9c259d
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullcom.cld
@@ -0,0 +1,765 @@
+!
+! BULLCOM.CLD
+!
+! VERSION 4/10/97
+!
+ 	MODULE BULLETIN_SUBCOMMANDS
+
+	DEFINE VERB ADD
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER BELL, NONNEGATABLE
+		QUALIFIER BROADCAST, NONNEGATABLE
+		DISALLOW NOT BROADCAST AND ALL
+		DISALLOW NOT BROADCAST AND BELL
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER CLUSTER, DEFAULT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT, NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		NONNEGATABLE
+		QUALIFIER LIST,DEFAULT
+		QUALIFIER LOCAL, NONNEGATABLE
+		DISALLOW LOCAL AND NOT BROADCAST
+		DISALLOW NODES AND SELECT_FOLDER
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		DISALLOW PERMANENT AND SHUTDOWN
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM, NONNEGATABLE
+	DEFINE VERB ATTACH
+		PARAMETER P1, LABEL=PROCESS, VALUE(TYPE=$FILE)
+		QUALIFIER PARENT
+		DISALLOW NOT PARENT AND NOT PROCESS
+		DISALLOW PARENT AND PROCESS
+	DEFINE VERB BACK
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB CHANGE
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER GENERAL, NONNEGATABLE
+		QUALIFIER HEADER, NONNEGATABLE
+		QUALIFIER NEW,NONNEGATABLE
+		QUALIFIER NUMBER, VALUE(TYPE=$FILE,REQUIRED)
+		QUALIFIER OWNER, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM,NONNEGATABLE
+		QUALIFIER TEXT, NONNEGATABLE
+		DISALLOW ALL AND NUMBER
+		DISALLOW NEW AND NOT EDIT
+		DISALLOW SYSTEM AND GENERAL
+		DISALLOW PERMANENT AND SHUTDOWN
+		DISALLOW PERMANENT AND EXPIRATION
+		DISALLOW SHUTDOWN AND EXPIRATION
+		DISALLOW SUBJECT AND HEADER
+	DEFINE VERB COPY
+		PARAMETER P1, LABEL=FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER ALL
+		QUALIFIER LOCAL
+		QUALIFIER MERGE
+		QUALIFIER ORIGINAL
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB CREATE
+		QUALIFIER ADD_ONLY, NONNEGATABLE
+		QUALIFIER ALWAYS, NONNEGATABLE
+		QUALIFIER BRIEF, NONNEGATABLE
+		QUALIFIER COMPRESS, NONNEGATABLE
+		QUALIFIER COPY, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER DESCRIPTION, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER ID, NONNEGATABLE
+!
+! Add ,DEFAULT to the end of the following line if you want CREATE to be
+! a privileged command.  NOTE: Make sure that BULL_DIR:BULLUSER.DAT
+! has the following protection:  (RWED,RWED,,)
+!
+		QUALIFIER NEEDPRIV, NONNEGATABLE
+		QUALIFIER NEWS
+		QUALIFIER NODE, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER NOTIFY, NONNEGATABLE
+		QUALIFIER OWNER, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER POST_ONLY, NONNEGATABLE
+		QUALIFIER PRIVATE, NONNEGATABLE
+		QUALIFIER READNEW, NONNEGATABLE
+		QUALIFIER REMOTENAME, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SEMIPRIVATE, NONNEGATABLE
+		QUALIFIER SHOWNEW, NONNEGATABLE
+		QUALIFIER SYSTEM, NONNEGATABLE
+		PARAMETER P1, LABEL=CREATE_FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		DISALLOW ID AND NOT OWNER
+		DISALLOW PRIVATE AND SEMIPRIVATE
+		DISALLOW BRIEF AND READNEW
+		DISALLOW SHOWNEW AND READNEW
+		DISALLOW BRIEF AND SHOWNEW
+		DISALLOW NODE AND (NOTIFY OR PRIVATE OR SEMIPRIVATE)
+		DISALLOW REMOTENAME AND NOT NODE
+		DISALLOW POST_ONLY AND ADD_ONLY
+	DEFINE VERB CURRENT
+		QUALIFIER EDIT
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB DELETE
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER IMMEDIATE,NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER FORCE
+		QUALIFIER LOCAL
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		QUALIFIER REASON, VALUE(REQUIRED)
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+		DISALLOW NOT SUBJECT AND (NODES OR SELECT_FOLDER)
+		DISALLOW NODES AND SELECT_FOLDER
+	DEFINE TYPE SEARCH_MATCHES
+	   	KEYWORD AND
+	   	KEYWORD OR
+	      		DEFAULT
+	   	KEYWORD XOR
+	DEFINE VERB DIRECTORY
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER ALL
+		QUALIFIER CONTINUE
+		QUALIFIER NEWS, SYNTAX=DIRECTORY_NEWS, NONNEGATABLE
+		QUALIFIER END, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER EXPIRATION
+		QUALIFIER EXTRACT, VALUE(TYPE=$FILE,REQUIRED)
+		QUALIFIER FEEDBACK
+		QUALIFIER FF
+		QUALIFIER FO, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+		QUALIFIER FOLDER, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+                QUALIFIER GROUP, VALUE(REQUIRED,LIST)
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW
+		QUALIFIER NOTIFY, DEFAULT
+		QUALIFIER PRINT
+		QUALIFIER QUEUE, VALUE(DEFAULT=SYS$PRINT), NONNEGATABLE
+                QUALIFIER FORM, VALUE, NONNEGATABLE
+		QUALIFIER MATCH, VALUE(DEFAULT="OR",TYPE=SEARCH_MATCHES)
+		QUALIFIER NOW
+		QUALIFIER OUTPUT,VALUE(REQUIRED,TYPE=$FILE)
+		QUALIFIER POST, DEFAULT
+		QUALIFIER START, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER ROTATE
+		QUALIFIER SEARCH, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SUBJECT, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER FROM, VALUE(REQUIRED), NONNEGATABLE
+                QUALIFIER NEGATED
+                DISALLOW GROUP AND
+			 NOT (SUBJECT OR SEARCH OR FROM OR NOREPLIES)
+                DISALLOW NEGATED AND 
+			 NOT (SUBJECT OR SEARCH OR FROM OR NOREPLIES)
+		DISALLOW (SUBJECT AND SEARCH) OR (SEARCH AND REPLY)
+		DISALLOW (FROM AND SUBJECT) OR (FROM AND NOREPLIES)
+		DISALLOW (NOREPLIES AND SUBJECT) OR (REPLY AND NOREPLIES)
+		DISALLOW (REPLY AND SUBJECT) OR (REPLY AND FROM)
+		DISALLOW (REPLY OR SUBJECT OR SEARCH OR FROM) AND
+			 (MARKED OR SEEN OR UNMARKED OR UNSEEN)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+		DISALLOW ALL AND (MARKED OR SEEN OR UNMARKED OR UNSEEN)
+		DISALLOW (NEW AND SINCE) OR (START AND NEW) OR (START AND SINCE)
+	DEFINE SYNTAX DIRECTORY_NEWS
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER NEWS, DEFAULT, NONNEGATABLE
+		QUALIFIER DEFAULT
+		QUALIFIER PERMANENT
+		QUALIFIER SUBSCRIBE
+		QUALIFIER FOLDER
+		QUALIFIER NEWGROUPS
+		QUALIFIER ALL
+		QUALIFIER STORED
+		QUALIFIER CLASS
+		QUALIFIER COUNT
+	DEFINE SYNTAX DIRECTORY_FOLDER
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER DESCRIBE
+		QUALIFIER FOLDER, DEFAULT
+		QUALIFIER NEWS, NONNEGATABLE
+	DEFINE VERB E				! EXIT command.
+	DEFINE VERB EX				! EXIT command.
+	DEFINE VERB EXIT			! EXIT command.
+	DEFINE VERB EXCLUDE
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL
+		QUALIFIER LIMIT, VALUE
+		QUALIFIER SUBJECT
+		DISALLOW FULL AND (ALL OR P1 OR FROM OR SUBJECT)
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB EXTRACT
+		PARAMETER P1, LABEL=EXTRACT, VALUE(TYPE=$FILE)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER ALL
+		QUALIFIER FF
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW, NONNEGATABLE
+		QUALIFIER ROTATE
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB FILE
+		PARAMETER P1, LABEL=EXTRACT, VALUE(TYPE=$FILE)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER ALL
+		QUALIFIER FF
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW, NONNEGATABLE
+		QUALIFIER ROTATE
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB FIRST
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB FORWARD
+		PARAMETER P1, LABEL=RECIPIENTS, PROMPT="Recipients"
+		VALUE(REQUIRED,IMPCAT,LIST)
+		QUALIFIER EDIT, NONNEGATABLE
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB HELP
+		PARAMETER P1, LABEL=HELP_FOLDER, VALUE(TYPE=$REST_OF_LINE)
+	DEFINE VERB INCLUDE
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL 
+		QUALIFIER LIMIT, VALUE
+		QUALIFIER SUBJECT, DEFAULT
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB THREAD
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL 
+		QUALIFIER LIMIT, VALUE, NONNEGATABLE
+		QUALIFIER SUBJECT, DEFAULT
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB INDEX
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER EXPIRATION
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER FOLDER, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+		QUALIFIER NEW, DEFAULT
+		QUALIFIER MATCH, VALUE(DEFAULT="OR",TYPE=SEARCH_MATCHES)
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER RESTART
+		QUALIFIER SEARCH, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER SET , DEFAULT
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SUBSCRIBE
+		QUALIFIER PERMANENT
+		QUALIFIER NEGATED
+		QUALIFIER FROM, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SUBJECT, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER START, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		DISALLOW (NEW AND SINCE) OR (START AND NEW) OR (START AND SINCE)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB LAST
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB MAIL
+		PARAMETER P1, LABEL=RECIPIENTS, PROMPT="Recipients"
+		VALUE(REQUIRED,IMPCAT,LIST)
+		QUALIFIER EDIT, NONNEGATABLE
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB MARK
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB MODIFY
+		QUALIFIER DESCRIPTION
+		QUALIFIER ID, NONNEGATABLE
+		QUALIFIER NAME, VALUE(REQUIRED)
+		QUALIFIER OWNER, VALUE(REQUIRED)
+		DISALLOW ID AND NOT OWNER
+	DEFINE VERB MOVE
+		PARAMETER P1, LABEL=FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER FORCE
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LOCAL
+		QUALIFIER MERGE
+		QUALIFIER NODES
+		QUALIFIER ORIGINAL
+		QUALIFIER IMMEDIATE,NONNEGATABLE,DEFAULT
+		DISALLOW ALL AND BULLETIN_NUMBER
+		DISALLOW FOLDER AND NODES
+	DEFINE VERB NEWS
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER NEWS, DEFAULT, NONNEGATABLE
+		QUALIFIER COUNT
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SUBSCRIBE
+		QUALIFIER DEFAULT
+		QUALIFIER PERMANENT
+		QUALIFIER NEWGROUPS
+		QUALIFIER ALL
+		QUALIFIER STORED
+		QUALIFIER CLASS
+		DISALLOW CLASS AND (SUBSCRIBE OR START OR ALL OR STORED
+			 OR PERMANENT OR DEFAULT)
+		DISALLOW NEWGROUPS AND (SUBSCRIBE OR START OR ALL OR STORED
+					OR PERMANENT OR DEFAULT)
+		DISALLOW (DEFAULT AND PERMANENT) OR (DEFAULT AND SUBSCRIBE)
+		DISALLOW PERMANENT AND SUBSCRIBE
+	DEFINE VERB N
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+                QUALIFIER ROTATE
+	DEFINE VERB NEXT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+                QUALIFIER ROTATE
+	DEFINE VERB POST
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER EDIT
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST, DEFAULT
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER NOSIGNATURE
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB PRINT
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NOTIFY, DEFAULT
+		QUALIFIER QUEUE, VALUE(DEFAULT=SYS$PRINT), NONNEGATABLE
+                QUALIFIER FORM, VALUE, NONNEGATABLE
+		QUALIFIER NOW
+		QUALIFIER CANCEL
+		QUALIFIER ALL
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB QUIT
+	DEFINE VERB READ
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$NUMBER)
+		QUALIFIER ALL
+		QUALIFIER EDIT
+		QUALIFIER HEADER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER NEW
+		QUALIFIER PAGE, DEFAULT
+		QUALIFIER POST, DEFAULT
+		QUALIFIER ROTATE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER THREADS
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		DISALLOW NEW AND SINCE
+		DISALLOW BULLETIN_NUMBER AND (ALL OR NEW OR SINCE)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB REPLY
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER BELL, NONNEGATABLE
+		QUALIFIER BROADCAST, NONNEGATABLE
+		DISALLOW NOT BROADCAST AND ALL
+		DISALLOW NOT BROADCAST AND BELL
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER CLUSTER, DEFAULT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT, NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST,DEFAULT
+		QUALIFIER LOCAL
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		NONNEGATABLE
+		DISALLOW LOCAL AND NOT BROADCAST
+		DISALLOW NODES AND SELECT_FOLDER
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		DISALLOW PERMANENT AND SHUTDOWN
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM, NONNEGATABLE
+	DEFINE VERB REMOVE
+		PARAMETER P1, LABEL=REMOVE_FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+	DEFINE VERB RESET
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER CURRENT
+		DISALLOW CURRENT AND NUMBER
+	DEFINE VERB RESPOND
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		DISALLOW GROUPS AND NOT LIST
+		QUALIFIER EDIT
+	DEFINE VERB SEARCH
+		PARAMETER P1, LABEL=SEARCH_STRING, VALUE(LIST) 
+		QUALIFIER EDIT
+		QUALIFIER FEEDBACK
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER FROM
+                QUALIFIER GROUP, VALUE(REQUIRED,LIST)
+                QUALIFIER NEGATED
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER REVERSE
+		QUALIFIER START, VALUE(TYPE=$NUMBER)
+		QUALIFIER SUBJECT
+		QUALIFIER MATCH, VALUE(REQUIRED)
+		DISALLOW NOT (SEARCH_STRING OR REPLY) AND REVERSE
+		DISALLOW SEARCH_STRING AND REPLY
+		DISALLOW GROUP AND SELECT_FOLDER
+	DEFINE VERB SEEN
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER READ
+		DISALLOW (NUMBER AND (NEG READ OR READ))
+	DEFINE VERB SELECT
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB SET
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER ID
+	DEFINE TYPE SET_OPTIONS
+		KEYWORD NODE, SYNTAX=SET_NODE
+		KEYWORD NONODE, SYNTAX = SET_NONODE
+		KEYWORD EXPIRE_LIMIT, SYNTAX=SET_EXPIRE
+		KEYWORD NOEXPIRE_LIMIT
+		KEYWORD GENERIC, SYNTAX=SET_GENERIC
+		KEYWORD NOGENERIC, SYNTAX=SET_GENERIC
+		KEYWORD LIBRARY, SYNTAX=SET_LIBRARY
+		KEYWORD LOGIN, SYNTAX=SET_LOGIN
+		KEYWORD NOLOGIN, SYNTAX=SET_LOGIN
+		KEYWORD NOBBOARD
+		KEYWORD BBOARD, SYNTAX=SET_BBOARD
+		KEYWORD NOBRIEF, SYNTAX=SET_NOFLAGS
+		KEYWORD BRIEF, SYNTAX=SET_FLAGS
+		KEYWORD NOSHOWNEW, SYNTAX=SET_NOFLAGS
+		KEYWORD SHOWNEW, SYNTAX=SET_FLAGS
+		KEYWORD NOREADNEW, SYNTAX=SET_NOFLAGS
+		KEYWORD READNEW, SYNTAX=SET_FLAGS
+		KEYWORD ACCESS, SYNTAX=SET_ACCESS
+		KEYWORD NOACCESS, SYNTAX=SET_NOACCESS
+		KEYWORD FOLDER, SYNTAX=SET_FOLDER
+		KEYWORD NOTIFY, SYNTAX=SET_FLAGS
+		KEYWORD NONOTIFY, SYNTAX=SET_NOFLAGS
+		KEYWORD PRIVILEGES, SYNTAX=SET_PRIVILEGES
+		KEYWORD DUMP
+		KEYWORD NODUMP
+		KEYWORD PAGE
+		KEYWORD NOPAGE
+		KEYWORD SYSTEM
+		KEYWORD NOSYSTEM
+		KEYWORD KEYPAD
+		KEYWORD NOKEYPAD
+		KEYWORD PROMPT_EXPIRE
+		KEYWORD NOPROMPT_EXPIRE
+		KEYWORD DEFAULT_EXPIRE, SYNTAX=SET_DEFAULT_EXPIRE
+		KEYWORD STRIP
+		KEYWORD NOSTRIP
+		KEYWORD DIGEST
+		KEYWORD NODIGEST
+		KEYWORD CONTINUOUS_BRIEF
+		KEYWORD NOCONTINUOUS_BRIEF
+		KEYWORD ALWAYS
+		KEYWORD NOALWAYS
+		KEYWORD COMPRESS
+		KEYWORD NOCOMPRESS
+		KEYWORD POST_ONLY
+		KEYWORD NOPOST_ONLY
+		KEYWORD ADD_ONLY
+		KEYWORD NOADD_ONLY
+		KEYWORD NEWS, SYNTAX=SET_NEWS 
+		KEYWORD ANONYMOUS
+		KEYWORD NOANONYMOUS
+		KEYWORD EXLIMIT,SYNTAX=SET_EXLIMIT
+		KEYWORD EXCLUDE
+		KEYWORD NOEXCLUDE
+		KEYWORD NAME,SYNTAX=SET_NAME
+		KEYWORD SUBSCRIBE, SYNTAX=SET_SUBSCRIBE
+		KEYWORD FILE_DIRECTORY,SYNTAX=SET_FILE_DIRECTORY
+		KEYWORD GATEWAY
+		KEYWORD NOGATEWAY
+	DEFINE SYNTAX SET_EXLIMIT
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SET_PARAM2
+			VALUE(REQUIRED,TYPE=$NUMBER)
+	DEFINE SYNTAX SET_FILE_DIRECTORY
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SET_PARAM2
+	DEFINE SYNTAX SET_NAME
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=OLDNAME, VALUE(REQUIRED)
+		PARAMETER P3, LABEL=NEWNAME, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_NODE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=NODENAME, VALUE(REQUIRED)
+		PARAMETER P3, LABEL=REMOTENAME
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_NONODE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_EXPIRE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=EXPIRATION, VALUE(TYPE=$NUMBER,REQUIRED)
+	DEFINE SYNTAX SET_GENERIC
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME, VALUE(REQUIRED)
+		QUALIFIER DAYS,VALUE(TYPE=$NUMBER,DEFAULT="7"),DEFAULT
+	DEFINE SYNTAX SET_LOGIN
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_LIBRARY 
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=LIBRARY, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_FLAGS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+	DEFINE SYNTAX SET_NOFLAGS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+	DEFINE SYNTAX SET_SUBSCRIBE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+		DISALLOW NOT (ALL OR DEFAULT OR NODEFAULT OR PERMANENT
+			 OR NOPERMANENT)
+	DEFINE SYNTAX SET_BBOARD
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=BB_USERNAME
+		QUALIFIER EXPIRATION, VALUE(TYPE=$NUMBER)
+			LABEL=EXPIRATION, DEFAULT
+		QUALIFIER SPECIAL, NONNEGATABLE
+		QUALIFIER VMSMAIL, NONNEGATABLE
+		DISALLOW VMSMAIL AND NOT SPECIAL
+		DISALLOW VMSMAIL AND NOT BB_USERNAME
+	DEFINE SYNTAX SET_FOLDER
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SELECT_FOLDER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE SYNTAX SET_NOACCESS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=ACCESS_ID, VALUE(LIST)
+		PARAMETER P3, LABEL=ACCESS_FOLDER
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER CLASS, NONNEGATABLE
+		QUALIFIER READONLY, NONNEGATABLE
+		DISALLOW NOT ALL AND NOT ACCESS_ID
+		DISALLOW ALL AND NOT READONLY
+	DEFINE SYNTAX SET_NEWS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+		QUALIFIER ALL, DEFAULT
+		QUALIFIER CLASS,VALUE(REQUIRED)
+		QUALIFIER DEFAULT, NONNEGATABLE 
+		QUALIFIER DELETE, NONNEGATABLE 
+		QUALIFIER DISABLE, NONNEGATABLE
+		QUALIFIER ENABLE, NONNEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE(REQUIRED,
+				TYPE=$NUMBER)
+		QUALIFIER FULL
+		QUALIFIER LIMIT, NONNEGATABLE, VALUE(REQUIRED, 
+				TYPE=$NUMBER) 
+		QUALIFIER PRIVATE
+		QUALIFIER STORED
+  		DISALLOW (DEFAULT AND CLASS) OR (DELETE AND NOT CLASS)
+  		DISALLOW DEFAULT AND (DISABLE OR ENABLE OR PRIVATE)
+	DEFINE SYNTAX SET_ACCESS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=ACCESS_ID, VALUE(LIST)
+		PARAMETER P3, LABEL=ACCESS_FOLDER
+		QUALIFIER READONLY, NONNEGATABLE
+		QUALIFIER CLASS, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		DISALLOW NOT ALL AND NOT ACCESS_ID
+	DEFINE SYNTAX SET_PRIVILEGES
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=PRIVILEGES, PROMPT="Privileges"
+		VALUE (REQUIRED,LIST)
+	DEFINE SYNTAX SET_DEFAULT_EXPIRE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=DEFAULT_EXPIRE, VALUE(TYPE=$NUMBER,REQUIRED)
+	DEFINE VERB SHOW
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+!
+! The following are defined to allow qualifiers to be specified
+! directly after the SHOW command, i.e. SHOW/FULL FOLDER.
+! Otherwise, the CLI routines will reject the command, because it
+! first attempts to process the qualifier before process the parameter,
+! so it has no information the qualifiers are valid.
+!
+		QUALIFIER FULL, SYNTAX=SHOW_FOLDER_FULL, NONNEGATABLE
+		QUALIFIER ALL, SYNTAX=SHOW_USER
+		QUALIFIER FOLDER, VALUE, SYNTAX=SHOW_USER
+		QUALIFIER LOGIN, SYNTAX=SHOW_USER
+		QUALIFIER NOLOGIN, SYNTAX=SHOW_USER
+		QUALIFIER PRINT, SYNTAX=SHOW_KEYPAD_PRINT
+		QUALIFIER SINCE, VALUE(TYPE=$DATETIME), SYNTAX=SHOW_USER
+		QUALIFIER START, SYNTAX=SHOW_USER
+		QUALIFIER STATE, VALUE(LIST,DEFAULT=DEFAULT), NONNEGATABLE
+	DEFINE TYPE SHOW_OPTIONS
+		KEYWORD EXCLUDE
+		KEYWORD FLAGS, SYNTAX=SHOW_FLAGS
+		KEYWORD FOLDER, SYNTAX=SHOW_FOLDER
+		KEYWORD INCLUDE
+		KEYWORD KEYPAD, SYNTAX=SHOW_KEYPAD
+		KEYWORD LIBRARY, SYNTAX=SHOW_LIBRARY
+		KEYWORD NEW, SYNTAX=SHOW_FLAGS
+		KEYWORD PRIVILEGES, SYNTAX=SHOW_FLAGS
+		KEYWORD THREAD
+		KEYWORD USER, SYNTAX=SHOW_USER
+		KEYWORD VERSION
+	DEFINE SYNTAX SHOW_FLAGS
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+	DEFINE SYNTAX SHOW_KEYPAD
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+                PARAMETER P2, LABEL=SHOW_KEY
+		QUALIFIER PRINT
+		DISALLOW PRINT AND SHOW_KEY
+		QUALIFIER STATE, VALUE(LIST,DEFAULT=DEFAULT), NONNEGATABLE
+			DEFAULT
+	DEFINE SYNTAX SHOW_KEYPAD_PRINT
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		QUALIFIER PRINT,DEFAULT
+	DEFINE SYNTAX SHOW_LIBRARY
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		QUALIFIER ALL
+	DEFINE SYNTAX SHOW_FOLDER
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+	DEFINE SYNTAX SHOW_USER
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME
+		QUALIFIER ALL
+		QUALIFIER FOLDER, VALUE
+		QUALIFIER LOGIN
+		QUALIFIER NOLOGIN
+		QUALIFIER SINCE, VALUE(TYPE=$DATETIME)
+		QUALIFIER START, VALUE
+		DISALLOW (NOLOGIN OR LOGIN OR ALL) AND USERNAME
+		DISALLOW (LOGIN AND NOLOGIN)
+		DISALLOW (LOGIN OR NOLOGIN) AND FOLDER
+	DEFINE SYNTAX SHOW_FOLDER_FULL
+		QUALIFIER FULL, DEFAULT
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+	DEFINE VERB SUBSCRIBE
+        DEFINE VERB SPAWN
+		PARAMETER P1, LABEL=COMMAND, VALUE(TYPE=$REST_OF_LINE)
+	DEFINE VERB UNMARK
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB UNDELETE
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+	DEFINE VERB UNSEEN
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB UNSUBSCRIBE
diff --git a/decus/vmslt98a/bulletin/bullcoms1.hlp b/decus/vmslt98a/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..fe43db7f27635c2ccb1e44f7903fe85d30201481
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullcoms1.hlp
@@ -0,0 +1,1261 @@
+1 ADD
+Adds a message to the specified folder.  A file can be  specified  which
+contains  the  message.    Otherwise, BULLETIN will prompt for the text.
+BULLETIN will ask for an expiration date and a  header  to  contain  the
+topic of the message. 
+
+  Format:
+    ADD [file-name]
+2 /ALL
+This option is restricted to privileged users.  It is used in conjunction
+with the /BROADCAST qualifier.  If specified, all terminals are sent the
+message.  Otherwise, only users are sent the message.
+2 /BELL
+This option is restricted to privileged users.  It is used in conjunction 
+with the /BROADCAST qualifier.  If specified, the bell is rung on the 
+terminals when the message is broadcasted.
+2 /BROADCAST
+This option is restricted to privileged users and SYSTEM  folders.    If
+specified,  a message is both stored and broadcasted to all users logged
+in at the time.  If the folder is remote, a message will be broadcast on
+all  nodes  which  are  connected  to  that  folder,  unless  /LOCAL  is
+specified.  A node which does not have  BULLCP  running  cannot  have  a
+message  broadcasted  to  it, (even though it is able to create a remote
+folder).   A broadcasted message is limited to 1600 characters
+
+See also /ALL and /BELL.
+2 /CLUSTER
+ /[NO]CLUSTER
+
+This option specifies that broadcasted messages should be sent to all
+nodes in the cluster.  /CLUSTER is the default.
+2 /EDIT
+ /[NO]EDIT
+Determines whether or not the editor is invoked to edit the message
+you are adding.  /EDIT is the default if you have added /EDIT to your
+BULLETIN command line.
+2 /EXPIRATION
+ /EXPIRATION=time
+
+Specifies the time at which the message is to expire.  Either absolute
+time: [dd-mmm-yyyy] hh:mm:ss, or delta time: dddd [hh:mm:ss] can be
+used.
+2 /EXTRACT
+Specifies that the text of the previously read message should be included
+at the beginning of the new message.  The previous message must be in the
+same folder.  This qualifier is valid only when used with /EDIT.  The
+text is indented with -> at the beginning of each line.  This can be
+suppressed or the indentation character changed with /[NO]INDENT.
+2 /FOLDER
+ /FOLDER=(foldername,[...])
+
+Specifies the foldername into which the message is to be  added.    Does
+not  change the current selected folder.  Folders can be either local or
+remote folders.  Thus, a  nodename  can  precede  the  foldername  (this
+assumes that the remote node is capable of supporting this feature, i.e.
+the BULLCP process is running on that node.  If  it  is  not,  you  will
+receive an error message).  If the the foldername is specified with only
+a nodename, i.e. FOO::, the foldername is  assumed  to  be  the  default
+folder.    NOTE: Specifying remote nodes is only possible if that remote
+node is running a special BULLCP process.  If it isn't, the only way  to
+add  messages  to  that  remote node is via the /NODE command.  /FOLDER,
+however, is a much quicker method, and much more versatile. 
+
+You can specify logical names which translate  to  one  or  more  folder
+names.   I.e.   $  DEFINE ALL_FOLDERS "VAX1,VAX2,VAX3", and then specify
+ALL_FOLDERS after /FOLDER=.  Note that the quotation marks are required.
+
+When using /FOLDER for remote nodes, proxy logins are used to  determine
+if privileged options are allowed.  If they are not allowed, the message
+will still be added, but without the privileged settings.
+2 /LOCAL
+Specifies  that  when  /BROADCAST  is specified for a remote folder, the
+message is broadcasted ONLY on the local node.
+2 /NODES
+ /NODES=(nodes[,...])
+
+Specifies  to send the message to the listed DECNET nodes.  The BULLETIN
+utility  must  be  installed  properly  on  the   other   nodes.    (See
+installation  notes). You can specify a different username to use at the
+other nodes by either using the USERNAME qualifier, or by specifying the
+nodename   with   2   semi-colons   followed   by   the  username,  i.e.
+nodename::username.  If you specify a username, you will be prompted for
+the password of the account on the other nodes.
+
+Additionally,  you  can  specify logical names which translate to one or
+more node names.  I.e.  $ DEFINE ALL_NODES  "VAX1,VAX2,VAX3",  and  then
+specify /NODES=ALL_NODES.  Note that the quotation marks are required.
+
+NOTE:  It  is  preferable  to  use /FOLDER instead of /NODE if possible,
+since adding messages via /FOLDER is much quicker.
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+2 /NOSIGNATURE
+Specifies to suppress the automatically appended signature, if one exists.
+Signatures are appended for postings to mailing lists and to responds.
+See the help topic POST Signature_file for signature information.
+2 /PERMANENT
+If specified, message will be a permanent message and will never expire.
+If an expiration limit is set, then permament is not allowed unless
+user has privileges.
+2 /SUBJECT
+ /SUBJECT=description
+
+Specifies the subject of the message to be added.
+2 /SHUTDOWN
+ /SHUTDOWN[=nodename]
+This option is restricted to privileged users.   If  specified,  message
+will  be  automatically  deleted after a computer shutdown has occurred.
+This option is restricted to SYSTEM folders. 
+
+If the bulletin files are shared between cluster nodes, the message will
+be  deleted  after  the  node on which the message was submitted from is
+rebooted.  If you wish the message to be deleted after a different  node
+reboots,  you have the option of specifying that node name.  The message
+deletion is keyed by BULLETIN running on the  node  that  reboots.    It
+writes  into  the  database  info  that  the node has rebooted, and when
+BULLCP wakes up and sees this info, it will delete any shutdown messages
+for that node. 
+
+NOTE: If the folder is a remote folder,  the  message  will  be  deleted
+after  the  remote node reboots, not the node from which the message was
+added.  The nodename cannot be specified with a remote folder. 
+2 /SYSTEM
+This option is restricted to privileged users.  If specified, message
+is both saved in the folder and displayed in full as a system message
+when a user logs in.  System messages should be as brief as possible to
+avoid the possibility that system messages could scroll off the screen.
+This option is restricted to SYSTEM folders.
+2 /USERNAME
+Specifies username to be used at remote DECNET nodes when adding messages
+to DECNET nodes via the /NODE qualifier.
+1 ATTACH
+Permits you to switch control of your terminal from your current process
+to another process in your job. 
+
+The ATTACH command allows you to move quickly between processes that you
+have created with the SPAWN command.  For example, while you are editing
+a file, you can SPAWN a subprocess to read a new  message.    Enter  the
+ATTACH  command to get back to back to the editing session.  If you want
+to read another new message, you can use the ATTACH command to get  back
+to the BULLETN subprocess you already created. 
+
+   Format:
+
+       ATTACH [/PARENT] [process-name]
+2 Parameters
+
+ process-name
+
+  Indicates the name of the subprocess to which the connection  is  to
+  be made. Only the /PARENT qualifier or a process-name may be specified.
+
+2 Qualifiers
+
+/PARENT
+
+   Allows you to attach to your process' parent process.
+   If there is no parent process an error message is printed.
+
+
+2 Examples
+
+  1.   
+       $ SPAWN BULLETIN
+       %DCL-S-SPAWNED, process MAGNANI_3 spawned
+       %DCL-S-ATTACHED, terminal now attached to process MAGNANI_3
+       BULLETIN> ATTACH MAGNANI_2
+       %DCL-S-RETURNED, control returned to process MAGNANI_2
+       $ ATTACH MAGNANI_3
+       BULLETIN>
+
+
+  This  example  shows  how  to  spawn  subprocesses  (MAGNANI_2   and
+  MAGNANI_3) to move from BULLETIN to DCL back to BULLETIN.  The ATTACH 
+  command  allows you to transfer control between subprocesses.
+
+
+                                  NOTE
+
+      You always SPAWN a new process and ATTACH to a process  that
+      already exists.
+1 BACK
+Displays the message preceding the current message.
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.
+If /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER for non-
+NEWS folders, /NOHEADER for NEWS folders.  If the SET STRIP command
+is set for the folder, it will change the default to be /HEADER.
+A user can make this option the default for a particular folder or
+news group.  See HELP Customizing.
+1 BULLETIN
+The BULLETIN utility permits a user to create a message for  reading  by
+all  users.    Users are notified upon logging in that new messages have
+been added, and what the topic of the messages are.  Actual  reading  of
+the  messages  is  optional.  (See  the  command SET READNEW for info on
+automatic  reading.)  Messages  are  automatically  deleted  when  their
+expiration date has passed. 
+1 CHANGE
+Replaces or modifies existing stored message.  This is for changing part
+or  all  of  a  message  without causing users who have already seen the
+message to be notified of it a second time.  You can  select  qualifiers
+so  that  either the message text, expiration date, or the header are to
+be changed.  If no qualifier is added, the default  is  that  all  these
+parameters  are  to  be  changed.    If the text of the message is to be
+changed, a file can be specified which contains the text.  If the editor
+is  used  for changing the text, the old message text will be extracted.
+This can be suppressed by the qualifier /NEW. 
+
+  Format:
+    CHANGE [file-name]
+2 /ALL
+Makes the changes to all the messages in the folder.  Only the expiration
+date and message headers can be changed if this qualifier is specified.
+2 /EDIT
+ /[NO]EDIT
+Determines whether or not the editor is invoked to edit the message
+you are replacing.  The old message text is read into the editor unless
+a file-name or /NEW is specified.  /EDIT is the default if you have
+added /EDIT to your BULLETIN command line.
+2 /EXPIRATION
+ /EXPIRATION[=time]
+
+Specifies the time at which the message is to expire.  Either absolute
+time: [dd-mmm-yyyy] hh:mm:ss, or delta time: dddd [hh:mm:ss] can be
+used.  If no time is specified, you will be prompted for the time.
+2 /GENERAL
+Specifies that the message is to be converted from a SYSTEM message to
+a GENERAL message.
+2 /HEADER
+Specifies that the message header is to be replaced.  You will be
+prompted for the new message description.
+2 /OWNER
+ /OWNER=string
+
+Specifies a new owner name.  Can only be changed if you own the folder
+or have privileges.
+2 /NEW
+If the editor is to be used for replacing the text of the message,
+NEW specifies not to read in the old message text, and that a totally
+new text is to be read in.
+2 /NUMBER
+ /NUMBER=message_number[-message_number1]
+
+Specifies the message or messages to be replaced. If this  qualifier  is
+omitted,  the  message that is presently being read will be replaced.  A
+range of  messages  can  be  specified,  i.e.  /NUMBER=1-5.    Only  the
+expiration  date  and  message  headers  can  be  changed  if a range is
+specified. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+2 /PERMANENT
+Specifies that the message is to be made permanent.
+2 /SHUTDOWN
+ /SHUTDOWN[=nodename]
+Specifies that the message is to expire after the next computer
+shutdown.  This option is restricted to SYSTEM folders.
+2 /SUBJECT
+ /SUBJECT=description
+
+Specifies the subject of the message to be added.
+2 /SYSTEM
+Specifies that the message is to be made a SYSTEM message.  This is a
+privileged command and is restricted to SYSTEM folders.
+2 /TEXT
+Specifies that the message text is to be replaced.
+1 COPY
+Copies a message to another folder  without  deleting  it  from  the
+current folder.
+
+  Format:
+
+    COPY folder-name [message_number][-message_number1]
+
+The folder-name is the name of the folder to which the message is to be
+copied to.  Optionally, a range of messages which are to be copied can be
+specified following the folder name, i.e. COPY NEWFOLDER 2-5.
+
+The key words CURRENT and LAST can also be specified in the range,
+in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.
+2 /ALL
+Specifies to copy all the messages in the old folder.
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected.  Specifies to send the message to
+the specified NEWS group(s) in addition to the selected NEWS group.
+2 /HEADER
+ /[NO]HEADER
+
+Valid only if destination folder is a news group.  Specifies that header
+of message is to be included with the text when the text is copied.
+The default is /NOHEADER.
+2 /LOCAL
+If specified and destination is a folder, the message will only be copied 
+to the folder, and will not be emailed to a corresponding email address or
+sent to a an associated news group, if either is present for the folder.
+If the destination is a news group, message header has line added to it
+to avoid having the message from being copied to a folder which has that
+news group feeding to it.
+2 /MERGE
+Specifies that the original date and time of the copied messages are
+saved and that the messages are placed in correct chronological order 
+in the new folder.  This operation is lengthy if the new folder is large.
+2 /ORIGINAL
+Specifies that the owner of the copied message will be the original owner
+of the message.  The default is that the copied message will be owned by
+the person copying the message.
+1 CREATE
+Creates a folder of messages.  This is similar to the folders in the VMS
+MAIL utility.  Folders are often created so that messages of  a  similar
+topic are grouped separately, or to restrict reading of certain messages
+to  specified  users.   Once  created,  that  message  is  automatically
+selected  (see information on SELECT command).  The commands that can be
+used to modify the folder's characteristics  are:  MODIFY,  REMOVE,  SET
+ACCESS, SET BBOARD, SET NODE, and SET SYSTEM.
+
+  Format:
+    CREATE folder-name
+
+The  folder-name is limited to 25 letters and must not include spaces or
+characters that are also invalid  in  filenames  (this  is  because  the
+folder is stored in a file name created with the folder name).
+
+NOTE:  Creation  of folders may be a restricted command if the installer
+has  elected  to  install  it  as  such.   This  is  done  by  modifying
+BULLCOM.CLD.
+2 /ALWAYS
+Specifies that  the  folder  has  the  ALWAYS  attribute.   This  causes
+messages  in  the  folder  to  be displayed differently when logging in.
+SYSTEM messages will be displayed every time a user logs in, rather than
+just  once.   Non-SYSTEM  message  will also be displayed every time (in
+whatever mode is selected, i.e. BRIEF, SHOWNEW, or  READNEW)  until  the
+user  actually  reads  that  message  (or a later one).  This feature is
+meant for messages which are very important, and thus you want  to  make
+sure they are read.
+2 /ADD_ONLY
+Specifies that the folder has the ADD_ONLY  attribute.    If  a  mailing
+address  is  present  (see /DESCRIPTION), when messages are added to the
+folder, they will also be mailed to the address.   Users  are  prevented
+from  using  the POST command.  Instead, the ADD command will be used if
+the POST command is entered.  One use for this is a local board which is
+also distributed to non-local users. 
+2 /BRIEF
+Specifies that all users automatically have BRIEF set for  this  folder.
+Only  a privileged user can use this qualifier.  (See HELP SET BRIEF for
+more information.)
+2 /DESCRIPTION
+ /DESCRIPTION=description
+
+Specifies the description of the folder, which is  displayed  using  the
+SHOW FOLDER command.  If omitted, you are prompted for a description. 
+
+If this folder is to receive messages from a network  mailing  list  via
+the  BBOARD  feature,  and  you  wish  to  use the POST and RESPOND/LIST
+commands, the address of the mailing list  should  be  included  in  the
+description.  This is done by enclosing the address using <> and placing
+it at the end of the description, i.e. 
+
+              INFOVAX MAILING LIST <INFO-VAX@KL.SRI.COM>
+
+You can also use this feature to have messages  which  are  added  to  a
+folder  to  be  mailed to the email address.  This is common if you have
+users that don't have access to BULLETIN.  Note:  When  you  specify  an
+email address, the folder automatically will have the ADD_ONLY flag set,
+which causes both ADD and POST to both add a message and send  mail  the
+message.  Note that a message added to the folder via the BBOARD feature
+will also be mailed to the specified email address.  In this way,  users
+without  access  to  BULLETIN  can  add  messages by sending mail to the
+BBOARD account.  If you create a remote  folder  pointing  to  a  folder
+associated  with an email address, you must specify the email address in
+the description of the remote folder also.  Please also read  about  the
+SET GATEWAY command. 
+
+It is also possible to use the description to specify a news group from
+which messages are fed into the folder.  See the file FOLDER_TO_NEWS.TXT
+for more info.
+2 /ID
+Designates that the name  specified  as  the  owner  name  is  a  rights
+identifier.    The  creator's process must have the identifier presently
+assigned to it.  Any process which has that identifier  assigned  to  it
+will  be  able  to  control the folder as if it were the folder's owner.
+This is used to allow more than one  use  to  control  a  folder.    The
+identifier can not be any longer than 12 characters. 
+
+Note: This feature will not work during remote access to the folder.
+2 /NODE
+ /NODE=node
+
+Specifies that the folder is a remote folder at the specified node.    A
+remote folder is a folder in which the messages are actually stored on a
+folder at a remote DECNET node.  The specified node is checked to see if
+a  folder  of  the same name is located on that node.  If so, the folder
+will then be modified to point to that folder.  For example if there was
+a folder on node A with name INFO, and you issued the command: 
+                        CREATE INFO/NODE=A
+from node B, then if INFO is selected  on  node  B,  you  will  actually
+obtain  the  folder  INFO  on  node  A.  In this manner, a folder can be
+shared between more than one node. This capability is  only  present  if
+the  BULLCP  process  is running on the remote node via the BULL/STARTUP
+command.  If the remote folder name is different from the  local  folder
+name,  the  remote  folder  name  is  specified  using  the  /REMOTENAME
+qualifier. 
+
+NOTE: If a message is added to a remote  node,  the  message  is  stored
+immediately.    However,  a  user logging into another node might not be
+immediately alerted that the message is present.   That  information  is
+only  updated  every  15  minutes  (same  algorithm  for updating BBOARD
+messages), or if a user accesses that folder.  Thus, if  the  folder  is
+located on node A, and the message is added from node B, and a user logs
+in to node C, the BULLETIN login notification might not notify the  user
+of  the  message.  However, if the message is added with /BROADCAST, the
+message will be broadcasted immediately to all nodes. 
+2 /NOTIFY
+Specifies that all users automatically have NOTIFY set for this  folder.
+Only a privileged user can use this qualifier.  (See HELP SET NOTIFY for
+more information.)
+2 /OWNER
+ /OWNER=username
+Specifies the owner of the folder.  This is a privileged command.
+See also /ID.
+2 /POST_ONLY
+Specifies that the folder has the POST_ONLY attribute.  This causes 
+the ADD command to mail the message to the mailing address if it is 
+present (see /DESCRIPTION), rather than add to the folder.  
+2 /PRIVATE
+Specifies that the folder can only be accessed by users  who  have  been
+granted  access via the SET ACCESS command.  Note: This option uses ACLs
+and users who are granted access must be entered into  the  Rights  Data
+Base.   If the RDB does not exist on your system, a privileged user will
+have to create it.  If a user is not  in  the  RDB,  this  program  will
+automatically  enter  the user into it (unless this feature was disabled
+during the compilation of this program).  NOTE: See HELP SET ACCESS  for
+more info. 
+
+WARNING:  This command can not be used with remote nodes.    Create  the
+folder  without  it and then use SET ACCESS to change protection.  Also,
+access protection on the remote node will override local protection. 
+2 /READNEW
+Specifies that all users automatically have READNEW set for this folder.
+Only  a  privileged  user can use this qualifier.  (See HELP SET READNEW
+for more information.)
+2 /REMOTENAME
+ /REMOTENAME=foldername
+Valid only if /NODE is present, i.e. that the folder is a remote folder.
+Specifies the name of the remote folder name.  If not specified, it is
+assumed that the remote name is the same as the local name.
+2 /SHOWNEW
+Specifies that all users automatically have SHOWNEW set for this folder.
+Only a privileged user can use this qualifier.  (See HELP SET SHOWNEW for
+more information.)
+2 /SEMIPRIVATE
+Similar to /PRIVATE, except that the folder is restricted only with
+respect to adding or modifying messages.  All users can read the folder.
+
+WARNING:  This command can not be used with remote nodes.  Create the 
+folder without it and then use SET ACCESS to change protection.  Also,
+access protection on the remote node will override local protection.
+2 /SYSTEM
+Specifies that the folder is a SYSTEM folder.  A SYSTEM folder is
+allowed to have SYSTEM and SHUTDOWN messages added to it.  This is a
+privileged command.
+                                                         
+If this is a remote folder, /SYSTEM cannot be specified unless the
+folder at the other node is also a SYSTEM folder.
+1 Ctrl-C
+Except for when BULLETIN is awaiting input from the terminal, a 
+CTRL-C will cause BULLETIN to abort the execution of any command.  If
+BULLETIN is waiting for terminal input, a CTRL-C will cause BULLETIN
+to return to the BULLETIN> prompt.  If for some reason the user wishes
+to suspend BULLETIN, CTRL-Y will usually do so.  However, this is not
+always true, as BULLETIN will ignore the CTRL-Y if it has a data file
+opened at the time. (Otherwise it would be possible to put the files
+in a state such that they would be inaccessible by other users.)
+1 CURRENT
+Displays the beginning of the message you are currently reading.  If
+you  are  reading  a long message and want to display the first part
+of the message again, you can enter the CURRENT command.
+
+  Format:
+
+    CURRENT
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.  If
+either /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER  for  non-
+NEWS  folders,  /NOHEADER for NEWS folders.  If the SET STRIP command is
+set for the folder, it will change the default to be /HEADER.    A  user
+can  make this option the default for a particular folder or news group.
+See HELP Customizing. 
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
+1 DELETE
+Deletes the specified message.  If no message is specified, the  current
+message  is  deleted.   Only the original owner or a privileged user can
+delete a message.  Note that the message is not deleted immediately, but
+its expiration is set 15 minutes in the future.  This is to allow a user
+to recover the message using the UNDELETE command.    If  you  want  the
+message deleted immediately, use the /IMMEDIATE qualifier. 
+
+  Format:
+    DELETE [message_number][-message_number1]
+
+The message's relative number is found by the DIRECTORY command.  It  is
+possible  to  delete  a  range  of  messages  by  specifying two numbers
+separated by a dash, i.e. DELETE  1-5.    However,  a  range  cannot  be
+specified if the folder is remote. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+2 /ALL
+Specifies to delete all the messages in the folder.  Note:  This will
+not work for remote folders.  Only one message can be deleted from a
+remote folder at a time.
+2 /IMMEDIATE
+Specifies that the message is to be deleted immediately.  Not applicable
+to news groups that are stored on disk.
+2 /LOCAL
+Only used with news groups stored on disk.  Only the local message will
+be deleted.  No delete message will be sent to the Usenet network to
+delete the message at other nodes.
+2 /NODES
+ /NODES=(nodes[,...])
+
+Specifies to delete the  message  at  the  listed  DECNET  nodes.    The
+BULLETIN utility must be installed properly on the other nodes.  You can
+specify a different username to use at the other nodes by  either  using
+the USERNAME qualifier, or by specifying the nodename with 2 semi-colons
+followed by the username, i.e. nodename::username.   If  you  specify  a
+username,  you  will  be prompted for the password of the account on the
+other nodes.  The /SUBJECT must be specified to  identify  the  specific
+message that is to be deleted. 
+
+Additionally, you can specify logical names which translate  to  one  or
+more  node  names.   I.e.  $ DEFINE ALL_NODES "VAX1,VAX2,VAX3", and then
+specify /NODES=ALL_NODES.  Note that the quotation marks are required. 
+2 /SUBJECT
+ /SUBJECT=subject
+
+Specifies the subject of the bulletin to be deleted at a  remote  DECNET
+node.   The DECNET node must be specified with the /NODE qualifier.  The
+specified subject need not be the exact subject of the message.  It  can
+be  a  substring of the subject.  This is in case you have forgotten the
+exact subject that was specified.  Case is not  critical  either.    You
+will be notified if the deletion was successful.  See also /NEGATED. 
+2 /USERNAME
+Specifies username to be used  at  remote  DECNET  nodes  when  deleting
+messages on other DECNET nodes via the /NODE qualifier. 
+1 DIRECTORY
+Lists a summary of the messages.  The message number, submitter's  name,
+date, and subject of each message is displayed. 
+
+  Format:
+
+    DIRECTORY [folder]
+
+If  a  folder is specified, that folder is selected before the directory
+is listed.  Unless otherwise specified, listing starts  with  the  first
+newest message.  If there are no new messages, listing will start at the
+first message, or if a message has already been read, it will  start  at
+that message.
+2 /ALL
+Lists all messages.  Used if the qualifiers /MARKED, /UNMARKED, /SEEN,
+or /UNSEEN were previously specified. 
+2 /CONTINUE
+Used with /GROUP.  Allows you to continue a search after you have broken
+the  search by entering a command, i.e. READ, SEARCH, etc.  Note: If you
+enter a SEARCH command which specifies a string, and then  continue  the
+directory  search using /CONTINUE, the new search pattern will be used
+when continuing the search. 
+2 /DESCRIBE 
+Valid when used with /FOLDERS.  Specifies to include description of
+folder. 
+2 /EXPIRATION
+Shows the message's expiration date rather than the creation date.
+2 /END
+ /END=message_number
+
+Indicates the last message number you want to display.
+2 /EXTRACT
+ /EXTRACT=filename
+
+Specifies that the text of the messages which are found by the DIRECTORY
+command are to be written into the specified file.  All qualifiers which
+are valid for the EXTRACT command are valid in conjunction with /EXTRACT
+except  for /NEW which conflicts with the DIRECTORY /NEW qualifier.  The
+listof messages to be printed will be  displayed  on  the  terminal  (in
+nopaging format). 
+
+See the command SET FILE_DIRECTORY for info  on  setting  the  directory
+where files are stored.   The default directory is SYS$LOGIN.
+2 /FEEDBACK
+Used only in conjunction with /GROUP.  Specifies to show when  new  news
+groups are selected. 
+2 /FOLDERS
+Lists the available message folders.  Shows last message date and number
+of  messages  in  folder.   An asterisk (*) next to foldername indicates
+that there are unread messages in  that  folder.   This  will  not  show
+newsgroups.  To see newsgroups, use the NEWS command or DIR/NEWS.
+2 /FROM
+ /FROM=[string]
+
+Specifies that only messages whose username contains the specified string
+are to be displayed.  This cannot be used in conjunction with /MARKED.  
+If no string is specified, the previously specified string is used.
+See also /NEGATED.
+2 /GROUP
+   /GROUP=(string,[...])
+
+Specifies a list of groups  to  be  searched.    Used  with  the  search
+qualifiers  /SEARCH, /SUBJECT, or /FROM.  Wildcards are permitted in the
+specified string.  Use /FEEDBACK to see when groups are  selected.    At
+any  time  during the search you may enter other commands, i.e.  you may
+read a message, see a full directory listing, etc.  You may then restart
+the  search  listing by typing DIR/CONTINUE.  For more info, see help on
+the /CONTINUOUS qualifier. 
+2 /NEGATED
+Used with /SUBJECT, /FROM, & /SEARCH.  If specified, messages who don't
+match the specified search command are displayed.
+2 /MARKED
+Lists messages that have been marked (indicated by an asterisk).
+This is equivalent to selecting the folder with /MARKED, i.e. only
+marked messages will be shown and be able to be read.  To see all
+messages, use either /ALL, or reselect the folder. 
+2 /UNMARKED
+Lists messages that have not been marked (marked messages are indicated
+by an asterisk).  Using /UNMARKED is equivalent to selecting the folder
+with /UNMARKED, i.e. only unmarked messages will be shown and be able
+to be read.  To see all messages, use either /ALL, or reselect the
+folder. 
+2 /SEEN
+Lists messages that have been seen (indicated by a greater than sign). 
+Using /SEEN is equivalent to selecting the folder with /SEEN, i.e. only
+seen messages will be shown and be able to be read.  To see all
+messages, use either /ALL, or reselect the folder. 
+2 /UNSEEN
+Lists messages that have not been seen (seen message are indicated by a
+greater than sign). Using /UNSEEN is equivalent to selecting the folder
+with /UNSEEN, i.e. only unseen messages will be shown and be able to be
+read.  To see all messages, use either /ALL, or reselect the folder. 
+2 /NEW
+Specifies  to  start  the  listing  of  messages  with  the first unread
+message.
+2 /NEWS
+Lists the available news groups.  This does the same thing as  the  NEWS
+command.  See that command for qualifiers which apply.
+2 /OUTPUT
+ /OUTPUT=filename
+
+Specifies to write the directory output to a file rather than the
+terminal.
+2 /PRINT
+Specifies that the text of the messages which are found by the
+DIRECTORY command are to be printed.  All qualifiers which are valid
+for the PRINT command are valid in conjunction with /PRINT.  The list
+of messages to be printed will be displayed on the terminal (in
+nopaging format). 
+2 /REPLY
+Specifies that only messages which are replies to the current message
+are to be displayed.  This cannot be used in conjunction with /MARKED.
+2 /NOREPLIES
+Specifies that only messages which are not replies (i.e. whose subject
+do not start with RE:) are to be displayed.  This cannot be used in 
+conjunction with /MARKED.
+2 /SEARCH
+ /SEARCH=[string]
+
+Specifies that only messages which contain the specified string are
+to be displayed.  This cannot be used in conjunction with /MARKED.
+If no string is specified, the previously specified string is used.
+See also /NEGATED.
+2 /SINCE
+ /SINCE=date
+
+Displays a listing of all the messages created on or after the
+specified date.  If no date is specified, the default is TODAY.
+2 /START
+ /START=message_number
+
+Indicates the first message number you want to display.  For example,
+to  display  all the messages beginning with number three, enter the
+command line DIRECTORY/START=3.  Not valid with /FOLDER.
+2 /SUBJECT
+ /SUBJECT=[string]
+
+Specifies that only messages which contain the specified string in  it's
+subject  header are to be displayed.  This cannot be used in conjunction
+with /MARKED.  If no  string  is  specified,  the  previously  specified
+string is used. 
+1 EXCLUDE
+Specifies to exclude reading messages based on the message owner or  the
+subject.  If it is determined that a message is to be excluded, then the
+message is skipped when a user tries to read a message bytyping NEXT  or
+BACK,  or by hitting the return key.  Specify /FULL to make all EXCLUDEs
+and INCLUDEs for the  specified  folder  apply  to  all  other  BULLETIN
+commands, including directory listings.
+
+  Format:
+    EXCLUDE [string]
+
+If a string is specified, then the message is excluded if the  owner  or
+the subject contains that string, depending on whether /FROM or /SUBJECT
+is specified.  Otherwise, if no string is specified, then the owner name
+or subject of the current message is used.  /FROM is the default.
+
+Note:  EXCLUDEs take precedence over INCLUDEs.
+2 /ALL
+Used with /DISABLE to specify to disable all EXCLUDEs.
+2 /DISABLE
+Specifies to permanently disable the EXCLUDE.
+2 /FROM
+Specifies to exclude the message based on the message owner.  This is
+the default.  /FROM and /SUBJECT cannot be specified at the same time.
+2 /FULL
+If specified, causes all excludes and includes for the  selected  folder
+to  be  applied  to all BULLETIN commands, including directory listings.
+See help customizing for info on how to make this the  default  for  all
+folders.    Note  that  specifying  this  may  substantially  slow  down
+directory listings.  When /FULL is specified, the EXCLUDE  command  will
+not add an exclude,  so it can't be used with any other qualifier except
+for /DISABLE.
+2 /LIMIT
+   /LIMIT=days
+
+Specifies that the exclude will be automatically deleted if no match  is
+found  for the specified number of days.  The default is no limit, which
+is specified by 0.  This can be changed via the SET EXLIMIT command. 
+2 /SUBJECT
+Specifies to exclude the message based on the message subject.  /FROM
+and /SUBJECT cannot be specified at the same time. 
+2 Storing_EXCLUDEs
+EXCLUDEs are stored in the file SYS$LOGIN:BULL.CUSTOM or in the file
+pointed to by the logical name BULL_USER_CUSTOM.  The format is:
+
+folder_name:EXCLUDE:FROM(or SUBJECT):string
+
+In order for /FULL to be the default for a folder, the following line
+must be present:
+
+folder_name:defaults:kill
+
+excluding the folder_name causes it to apply to all folders.
+1 EXIT
+Exits the BULLETIN program.
+1 EXTRACT
+Synonym for FILE command.
+1 FILE
+Copies the current message to the named file.  If the file  exists,  the
+message is appended to the file, unless the /NEW qualifier is specified. 
+
+  Format:
+    FILE [filename] [message_number][-message_number1],[...]
+
+If the filename is omitted, a file will be created based on the name  of
+the folder. 
+
+A range of messages to be copied can optionally be specified, i.e.  FILE
+2-5.  The key words CURRENT and LAST can also be specified in the range,
+in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+
+See the command SET FILE_DIRECTORY for info  on  setting  the  directory
+where files are stored.   The default directory is SYS$LOGIN.
+2 /ALL
+Copies all the messages in the current folder.
+2 /FF
+Specifies that a form feed is placed between messages in the file.
+2 /HEADER
+ /[NO]HEADER
+
+Controls whether a header containing the owner, subject, and date of the 
+message is written in the file.  The default is to write the header.
+2 /NEW
+
+Specifies that a new file is to be created.  Otherwise, if the specified
+file exists, the file would be appended to that file.
+1 FIRST
+Specifies that the first message in the folder is to be read.
+1 Folders
+All messages are divided into separate folders.    New  folders  can  be
+created  by any user.  As an example, the following creates a folder for
+GAMES related messages: 
+                                               
+BULLETIN> CREATE GAMES
+Enter a one line description of folder.
+GAMES
+
+To see the list of available folders, use DIRECTORY/FOLDERS.  To  select
+a specific folder, use the SELECT command. 
+
+If a user selects a folder and enters the SET READNEW command, that user
+will  be  alerted of topics of new messages at login time, and will then
+be given the option of reading them.  Similar  to  READNEW  is  SHOWNEW,
+which displays the topics but doesn't prompt to read them.  Even less is
+SET BRIEF, which will cause only a one line output indicating that there
+are  new  messages  in the folder.  There also is the SET NOTIFY option,
+which will cause a message to be broadcast to a user's terminal alerting
+the user that a new message has been added.  Any of these options can be
+the default for the folder by using the /DEFAULT switch on the command. 
+
+A folder can be restricted to only certain users, if desired.   This  is
+done  by specifying CREATE/PRIVATE.  Afterwards, access to the folder is
+controlled by the creator by the SET [NO]ACCESS command.  If instead you
+specify /SEMIPRIVATE, all users can read the messages in the folder, but
+only those given access can add messages. 
+
+A folder can be converted into a remote folder using CREATE/NODE or  SET
+NODE.    A  remote  folder  is  one which points to a folder on a remote
+DECNET node.  Messages added to a remote node are actually stored on the
+folder   on   the   remote   node.    The  BULLCP  process  (created  by
+BULLETIN/STARTUP) must be running on the remote node for this option  to
+be used. 
+
+A folder can be specified as a SYSTEM folder, i.e. one in which  SYSTEM/
+SHUTDOWN/BROADCAST messages can be added.  One use for this is to create
+a remote SYSTEM folder which is shared by all nodes, so that the default
+folder is used for messages pertaining only to the local host, while the
+remote folder is used for messages pertaining to all nodes.  Another use
+is  to  create  a  folder  for  posting SYSTEM messages only meant for a
+certain UIC group.  This is done by creating a  PRIVATE  SYSTEM  folder,
+and  giving access to that UIC group.  Only users in that UIC group will
+see the messages in that folder when they log in. 
+1 FORWARD
+Synonym for MAIL command.
+1 HELP
+To obtain help on any topic, type:
+
+        HELP  topic
+1 INCLUDE
+This command is a synonym for the THREAD command.
+1 INDEX
+Gives directory listing of all folders or subscribed groups in
+alphabetical order.  Useful for scanning your folders or news groups for 
+new messages without having to manually select them.  If the INDEX
+command is re-entered while the INDEX scan is in progress, the scan will
+skip to the next folder.  This is useful for skipping past a folder.  It
+also can be used to continue the scan from where one left off after one
+has read a message.  /RESTART must be specified to start from the first
+folder if a scan is in progress.  All other qualifiers are ignored while 
+a scan is in progress.
+
+  Format:
+       INDEX
+
+When a directory is displayed, you can read the first message in the 
+list by typing READ.
+
+NOTE:  /NEW and /SET are the defaults.  This was not the case for older
+versions of BULLETIN.
+2 /MARKED
+Lists messages that have been marked (marked messages are indicated by
+an asterisk).  This is equivalent to selecting the folder with /MARKED,
+i.e. only marked messages will be shown and be able to be read. 
+2 /UNMARKED
+Lists messages that have not been marked (marked messages are indicated
+by an asterisk).  Using /UNMARKED is equivalent to selecting the folder
+with /UNMARKED, i.e. only unmarked messages will be shown and be able
+to be read.
+2 /SEEN
+Lists messages that have been seen (indicated by a greater than sign). 
+Using /SEEN is equivalent to selecting the folder with /SEEN, i.e. only
+seen messages will be shown and be able to be read.
+2 /UNSEEN
+Lists messages that have not been seen (seen message are indicated by a
+greater than sign). Using /UNSEEN is equivalent to selecting the folder
+with /UNSEEN, i.e. only unseen messages will be shown and be able to be
+read.
+2 /NEW
+ /[NO]NEW
+
+Specifies to list only those folders or groups that have new unread
+messages, and to start the listing with the first unread message.
+Otherwise, the listing will start with the first message.  /NEW is the
+default.  Is ignored if /[UN]SEEN or /[UN]MARKED are specified.
+2 /RESTART
+If specified, causes the listing to be reinitialized and start from the
+first folder.
+2 /SET
+ /[NO]SET
+
+Specifies that only folders that have READNEW, BRIEF, or SHOWNEW set are
+to be shown.  SET is the default.  Ignored if /SUBSCRIBE is specified.
+2 /SUBSCRIBE
+If specified, lists only news groups which have been subscribed to. 
+1 KEYPAD
+             +--------+--------+--------+--------+
+             | PF1    | PF2    | PF3    | PF4    |
+             |   GOLD |   HELP | EXTRACT|SHOW KEY|
+             |        |ST NOKEY|  FILE  |SH KY/PR|
+             |--------|--------|--------|--------|
+             | 7      | 8      | 9      | --     |
+             |  ADD   | REPLY  |  MAIL  |READ/NEW|
+             | ADD/EDI|RP/ED/EX|M/NOHEAD|SHOW NEW|
+             |--------|--------|--------|--------|
+             | 4      | 5      | 6      | ,      |
+             | CURRENT| RESPOND|  LAST  | DIR/NEW|
+             |CURR/EDI|RS/ED/EX|        |  INDEX |
+             |--------|--------|--------|--------|
+             | 1      | 2      | 3      |ENTER   |
+             |  BACK  |  PRINT |   DIR  |        |
+             |  NEXT  |P/NONOTI|DIR/FOLD|        |
+             |--------+--------|--------| ENTER  |
+             | 0               | .      | SELECT |
+             | SHOW FOLDER/FULL| DELETE |        |
+             |    SHOW FLAGS   | UNDELE |        |
+             +-----------------+--------+--------+
+2 Suggestions
+Here are keypads settings that the author personally uses.    Note  that
+the IND/SUBS commands are useful only for reading NEWS. 
+
+DEFINE/KEY PERIOD "IND/SUBS"/TERM
+DEFINE/KEY PERIOD "IND/SUBS/NONEW"/IF_STATE=GOLD/TERM  
+DEFINE/KEY MINUS "READ/THREAD"/IF_STATE=GOLD/TERM
+DEFINE/KEY PF1 ""/IF_STATE=GOLD/SET=NOEDIT
+DEFINE/KEY PF1 ""/IF_STATE=NOEDIT/SET=NOH
+DEFINE/KEY PF3 "EXT"/TERM
+DEFINE/KEY KP9 "MAIL/EDIT/NOHEAD"/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP8 "REPLY/NOEDIT"/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP7 "SEND/NOEDIT"/IF_STATE=NOEDIT/TERM 
+DEFINE/KEY KP4 "CUR/H"/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP4 "CUR/NOH"/IF_STATE=NOH/TERM
+DEFINE/KEY KP5 "RESPOND/NOEDIT "/IF_STATE=NOEDIT/TERM
+DEFINE/KEY KP5 "RESPOND/EXTRACT/LIST/EDIT "/TERM
+DEFINE/KEY KP2 "SEARCH/REP "/TERM
+DEFINE/KEY KP2 "SEARCH/REV/REP "/TERM/IF_STATE=GOLD
+DEFINE/KEY KP2 "SEARCH/REV "/IF_STATE=NOEDIT
+DEFINE/KEY COMMA "SPAWN"/TERM
+1 LAST
+
+Displays the last message in the current folder.
+
+  Format:
+       LAST
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.
+If /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER for non-
+NEWS folders, /NOHEADER for NEWS folders.  If the SET STRIP command
+is set for the folder, it will change the default to be /HEADER.
+A user can make this option the default for a particular folder or
+news group.  See HELP Customizing.
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
+1 MAIL
+Invokes the VAX/VMS Personal Mail Utility (MAIL) to send the message
+which you are reading to the specified recipients.
+
+  Format:
+
+    MAIL recipient-name[s]
+
+The input for the recipient name is exactly the same format as used by
+the MAIL command at DCL level.  Note that this means when specifying an
+address that has quotes, in order to pass the quotes you must specify
+triple quotes.  I.e. a network address of the form xxx%"address" must
+be specified as xxx%"""address""".
+2 /EDIT
+Specifies that the editor is to be used to edit the message before
+mailing it.
+2 /HEADER
+ /[NO]HEADER
+
+Controls whether a header containing the owner, subject, and date of the 
+message is written in the mail.  The default is to write the header.
+2 /SUBJECT
+ /SUBJECT=text
+
+Specifies the subject of the mail message. If the text consists of more
+than one word, enclose the text in quotation marks (").
+
+If you omit this qualifier, the description of the message will be used
+as the subject.
+1 MARK
+Sets the current or message-id message as marked. Marked messages are
+displayed with an asterisk in the left hand column of the directory
+listing.  A marked message can serve as a reminder of important
+information.  The UNMARK command sets the current or message-id message
+as unmarked.
+
+   Format:
+
+       MARK [message-number or numbers]
+       UNMARK [message-number or numbers]
+
+NOTE: The list of marked messages for non-NEWS folders are stored in a
+file username.BULLMARK, and NEWS folders are stored in
+username.NEWSMARK. The files are created in the directory pointed to by
+the logical name BULL_MARK.  If BULL_MARK is not defined, SYS$LOGIN
+will be used. 
+1 MODIFY
+Modifies the database information for the current folder.  Only the
+owner of the folder or a user with privileges can use this command. 
+
+  Format:
+
+    MODIFY
+2 /DESCRIPTION
+Specifies a new description for the folder.  You will be prompted for
+the text of the description.
+
+NOTE: If this folder is to receive messages from a network mailing  list
+via  the  BBOARD  feature, and you wish to use the POST and RESPOND/LIST
+commands, the address of the mailing list  should  be  included  in  the
+description.  This is done by enclosing the address using <> and placing
+it at the end of the description, i.e. 
+
+              INFOVAX MAILING LIST <INFO-VAX@KL.SRI.COM>
+
+You can also use this feature to have messages  which  are  added  to  a
+folder  to automatically mailed to the email address.  This is common if
+you have users that don't have access to BULLETIN.  In order to do this,
+you should use the SET ADD_ONLY command.  This causes all messages added
+to the folder to also be sent to the email address.  This  also  applies
+to  messages which are added via the BBOARD feature.  In this way, users
+without access to BULLETIN can add  messages  by  sending  mail  to  the
+BBOARD account.  Please also read about the SET GATEWAY command.
+2 /ID
+Designates that the name specified as the owner name is a rights
+identifier.  The creator's process must have the identifier presently
+assigned to it.  Any process which has that identifier assigned to it
+will be able to control the folder as if it were the folder's owner.
+This is used to allow more than one use to control a folder.
+
+Note: This feature will not work during remote access to the folder.
+2 /NAME
+ /NAME=foldername
+
+Specifies a new name for the folder.
+2 /OWNER
+ /OWNER=username
+
+Specifies a new owner for the folder.  If the owner does not have
+privileges, BULLETIN will prompt for the password of the new owner
+account in order to okay the modification.  See also /ID.
+1 MOVE
+Moves a message to another  folder  and  deletes  it  from  the  current
+folder. 
+
+  Format:
+
+    MOVE folder-name [message_number][-message_number1]
+
+The folder-name is the name of the folder to which the message is to  be
+be  moved to.  Optionally, a range of messages which are to be moved can
+be specified  following  the  folder  name,  i.e.  COPY  NEWFOLDER  2-5.
+However,  if  the  old  folder  is  remote,  they will be copied but not
+deleted, as only one message can be delted from a  remote  folder  at  a
+time. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+2 /ALL
+Specifies to move all the messages from the old folder.  Note:  If the
+old folder is remote, they will be copied but not deleted, as only one
+message can be deleted from a remote folder at a time.
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected.  Specifies to send the message to
+the specified NEWS group(s) in addition to the selected NEWS group.
+2 /HEADER
+ /[NO]HEADER
+
+Valid only if destination folder is a news group.  Specifies that header
+of message is to be included with the text when the text is copied.
+The default is /NOHEADER.
+2 /LOCAL
+If specified and destination is a folder, the message will only be moved
+to the folder, and will not be emailed to a corresponding email address or
+sent to a an associated news group, if either is present for the folder.
+If the destination is a news group, message header has line added to it
+to avoid having the message from being copied to a folder which has that
+news group feeding to it.
+2 /MERGE
+Specifies that the original date and time of the moved messages are
+saved and that the messages are placed in correct chronological order 
+in the new folder.  This operation is lengthy if the new folder is large.
+2 /ORIGINAL
+Specifies that the owner of the moved message will be the original owner
+of the message.  The default is that the moved message will be owned by
+the person moving the message.
+1 NEWS
+Displays the list of available news groups.
+
+Format:
+
+	NEWS [string]
+
+If  the  string is specified, lists news groups whose name contains that
+string.  If the string contains an asterisk, a wild card match  will  be
+applied.   I.e.  if ALT* is specified, all groups starting with ALT will
+be displayed.
+
+The status column of the display shows the status  of  the  news  group.
+"y"  means  the  news  group  is available.  "m" means the news group is
+moderated, and posting may or may not  be  allowable.    "="  means  the
+newsgroup  has  been renamed.  The new name is shown on the display line
+immediately following the old name. 
+
+Only those news groups which are enabled are shown.   Adding  /ALL  will
+show both enabled and disabled groups.  If this is done, the status will
+show "x" if the group has been deactived by the news  server  feed,  and
+"n" if the group has been deactived locally. 
+2 /ALL
+If specified, all news groups will be shown, including those that have
+been disabled.
+2 /CLASS
+If specified, will show news group classes.  For more info on classes,
+see help for SET NEWS/CLASS.
+2 /COUNT
+If specified, will show number of messages in the news group instead
+of the status.
+2 /DEFAULT
+If specified, will show news groups that have be defined as default 
+groups using the SET SUBSCRIBE command.
+2 /NEWGROUP
+If specified, will list new news groups that have been added since the
+last time that a user has accessed a news group.  If there are new
+groups, a user will see a message indicating that there are new groups
+when the user accesses a news group.
+2 /PERMANENT
+If specified, will show news groups that have be defined as permanent
+groups using the SET SUBSCRIBE command.
+2 /START
+ /START=string
+
+If specified, the list will start with the  first  group  which  follows
+alphabetically  after  that  string.  I.e. if /START=B is specified, the
+list will start with groups whose name starts with a B.
+2 /STORED
+If specified, only those news groups which are stored on disk are shown.
+2 /SUBSCRIBE
+If specified, lists only those news folders which have been subscribed to.
+An asterisk before the group indicates that new messages are present for
+that folder.
+1 New_features
+Here is a list of new features which may be of interest to the general 
+BULLETIN user.  If you find a bug or have a good suggestion for a new 
+feature, send mail to MRL@PFC.MIT.EDU.
+
+-------------------------------------------------------------------------
+V 2.24
+Removed INCLUDE command and replaced it with the THREAD command.    This
+allows  you  to  save  and  easily  read new messages in threads via the
+READ/THREADS command.  11/13/95
+
+V 2.23
+Added /LIMIT to EXCLUDE and also the SET EXLIMIT command.   These  allow
+excludes to be specified so that they expire after a specified amount of
+days.  The SHOW EXCLUDE now will show the last time a message was found 
+that matched the exclude.  8/16/95
+
+Added /GROUP qualifier to DIRECTORY command to allow  specifying  groups
+to search using wild cards names.  8/3/95
+
+Added /GROUP qualifier to SEARCH command to allow specifying  groups  to
+search using wild cards names.  6/20/95
+
+V 2.22
+
+SHOW EXCLUDE and INCLUDE commands added.  5/16/95
+
+V 2.21
+
+Added /CANCEL to PRINT command which cancels previous print commands.
+10/28/94
+
+Added /FOLLOWUP to POST command when used with news groups.  It specifies
+which news group you want replies to your message to be sent to.  10/28/94
+
+V 2.20
+
+Logical names can be specified in POST/GROUPS=.  5/12/94
+
+Added SET FILE_DIRECTORY command.  5/11/94
+
+V 2.19
+
+Add /MATCH qualifier to SEARCH command, and allow more than 1 string to be
+specified.  12/2/93
+
+V 2.18
+
+Added SET [NO]EXCLUDE command to be  able  to  ignore  any  excludes  or
+includes that have been specified for that folder.  5/20/93
+
+V 2.17
+
+Added /FULL to EXCLUDE  and  INCLUDE  command  to  make  it  affect  all
+commands, such as directory listings.  5/13/93
+
+V 2.15
+
+A user can make /HEADER be made the default for a folder or news group by
+adding a line to the user's customization file.  2/21/93
+
+Added /EXTRACT qualifie to DIRECTORY command.  1/31/93
+
+V 2.13
+
+Added /[NO]HEADER and /ROTATE to NEXT (help said they were there, but they
+weren't).  1/15/93
+
+Added RESET command.  1/9/93
+
+V 2.12
+
+Added INCLUDE and EXCLUDE commands which allow avoiding reading messages
+based on subject and address headers.  12/15/92
+
+V 2.11
+
+NEWS command now by default shows only groups which are active. Can show all
+groups with /ALL command. /STORED and /COUNT are new qualifiers. 11/5/92
+
+INDEX command modified to make it more useful. /NEW is now the default,  and
+now  only shows folders or groups that have new messages. /SET added to show
+only folders which have READNEW, SHOWNEW, or BRIEF  set,  and  /SET  is  the
+default. 11/5/92
+
+Folder names can now be up to 44 letters long.  11/5/92
+
+Added /ROTATE for read commands to allow reading messages encoded in  ROT-13
+coding.  This is used by some news groups to display messages which could be
+taken as being offensive (i.e. rec.humor.funny). 11/5/92
+1 NEXT
+Skips to the next message and displays it.  This is useful when paging
+through the messages and you encounter a particularly long message
+that you would like to skip over.
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.
+If /HEADER or /NOHEADER is specified, the setting will apply for all
+further reads in the selected folder.  The default is /HEADER for non-
+NEWS folders, /NOHEADER for NEWS folders.  If the SET STRIP command
+is set for the folder, it will change the default to be /HEADER.
+A user can make this option the default for a particular folder or
+news group.  See HELP Customizing.
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
diff --git a/decus/vmslt98a/bulletin/bullcoms2.hlp b/decus/vmslt98a/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..662cf64c52b91868be0ec4cc37a41eac511521a4
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullcoms2.hlp
@@ -0,0 +1,1463 @@
+1 POST
+If a NEWS group is selected, posts a message to that group.  If a normal
+folder is selected, sends a message via MAIL to the network mailing list
+which  is  associated  with  the  selected  folder.   The address of the
+mailing  list  must  be  stored  using  either   CREATE/DESCRIPTION   or
+MODIFY/DESCRIPTION.  See help on those commands for more information.
+
+  Format:
+    POST [file-name]
+2 /CC
+ /CC=user[s]
+Specifies additional users that should receive the mail message.
+2 /EDIT
+Specifies that the editor is to be used for creating the mail message.
+2 /EXTRACT
+Specifies that the text of the message that  is  being  read  should  be
+included  in  the  mail message.  This qualifier is valid only when used
+with /EDIT.  The text  of  the  message  is  indented  with  ->  at  the
+beginning  of  each  line.    This  can be suppressed or the indentation
+character changed with /[NO]INDENT.
+2 /FOLLOWUP
+ /FOLLOWUP=string
+
+Specifies that any replies  generated  by  people  reading  the  message
+should  be  sent to the specified newsgroup.  This is useful if you want
+to post to more than one group, but don't want reply messages posted  on
+all  the  groups.  To specify more than one newsgroup, surround the list
+with quotes, i.e.  FOLLOWUP="newsgroup1,newsgroup2".  If replies  should
+only  be  sent  to  the  message  owner  and not a newsgroup, the string
+"poster" should be specified. 
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected.  Specifies to send  the  message
+to  the  specified NEWS group(s) in addition to the selected NEWS group.
+Logical names are allowed. 
+2 /HEADER
+Allows customized headers line to be added to the message header.   When
+specified, header lines can be added by inserting them at the top of the
+message, with the header lines and the text of the message separated  by
+a blank line. 
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+2 /NOSIGNATURE
+Specifies to suppress  the  automatically  appended  signature,  if  one
+exists.    Signatures  are appended for postings to mailing lists and to
+responds.    See  the  help  topic  POST  Signature_file  for  signature
+information. 
+2 /SUBJECT
+ /SUBJECT=text
+
+Specifies the subject of the mail message. If the text consists of  more
+than one word, enclose the text in quotation marks ("). 
+
+If you omit this qualifier, you will prompted for the subject.
+2 Signature_file
+It is possibly to have the contents of a file be automatically  appended
+to  the end of a message added with the POST and/or the RESPOND command.
+This file is known as a signature file, and it typically contains  one's
+name, address, or perhaps a favorite quote.  The name of the file should
+be SYS$LOGIN:BULL_SIGNATURE.TXT, and it should be a  simple  text  file.
+In  order  to  specify  a different file to use, define the logical name
+BULL_SIGNATURE to point to the desired file. 
+
+It is possible to specify that portions or all of the signature file are
+to  be  included  only  for  specific  folders  or  news groups.  Simply
+surround the exclusive text starting with the line "START <folder-name>"
+and ending with the line "END", i.e. 
+
+START INFOVAX
+This line will only appear in the INFOVAX folder.
+END
+START MISC.TEST
+This line will only appear in the news folder MISC.TEST.
+END
+This line will appear in all postings.
+
+Note that an empty line is automatically created to separate the text of
+the message and the contents of the signature file.
+1 PRINT
+Queues a copy of the message you are currently  reading  (or  have  just
+read)  for  printing.    The  file  created  by the PRINT command is not
+released to the print queue until you exit, unless you add the qualifier
+/NOW or change one of the print job's qualifiers.  Multiple messages are
+concatenated into one print job. 
+
+   Format:
+
+       PRINT [message_number][-message_number1],[...]
+
+A range of messages to be printed  can  optionally  be  specified,  i.e.
+PRINT 2-5. 
+
+The key words CURRENT and LAST can also be specified in  the  range,  in
+place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc. 
+
+NOTE:  The qualifier /PRINT is present on the DIRECTORY command.    This
+provides  more  flexibility than is present with the PRINT command.  For
+example, if you want to print all messages with a particular  string  in
+it's subject line, DIRECTORY/PRINT/SUBJ would allow you do it. 
+2 /ALL
+Prints all the messages in the current folder.
+2 /CANCEL
+Cancels any messages waiting to be printed.
+2 /FORM
+Specifies the name or number of the form that you  want  for  the  print
+job.    Codes  for form types are installation-defined.  You can use the
+SHOW QUEUE/FORM command  at  DCL  level  to  find  out  the  form  types
+available for your system.  Use the SHOW QUEUE/FULL command at DCL level
+to find out the name of the mounted form and  the  default  form  for  a
+particular  queue.   If you specify a form whose stock is different from
+the stock of the form mounted on the queue, your  job  is  placed  in  a
+pending  state  until  the stock of the mounted form of the queue is set
+equal to the stock of the form associated with the job.   (In  order  to
+have  your  job  print,  the  system  manager  should  stop  the  queue,
+physically change the paper stock on the output device, and restart  the
+queue specifying the new form type as the mounted form.)
+2 /HEADER
+ /[NO]HEADER
+
+Controls whether a header containing the owner, subject, and date of the 
+message is printed at the beginning. The default is to write the header.
+2 /NOTIFY
+ /[NO]NOTIFY
+
+Indicates that you will be notified by a broadcast message when the file
+or  files  have  been  printed.   If /NONOTIFY is specified, there is no
+notification.  The default is /NOTIFY. 
+2 /NOW
+Sends all messages that have been queued for  printing  with  the  PRINT
+command during this session to the printer. 
+2 /QUEUE
+ /QUEUE=queue_name
+
+The name of the queue to which a message is to be sent.  If  the  /QUEUE
+qualifier  is not specified, the message is queued to SYS$PRINT.
+1 QUIT
+Exits the BULLETIN program.
+1 READ
+Displays the specified message.  If you do not specify a  message,  then
+the  first  time  you enter the command, the first message in the folder
+will be displayed.  However, if there are new messages,  the  first  new
+message  will  be  displayed.  Each time you enter the command, the next
+page, or if there are no more pages, the next message will be displayed. 
+
+  Format:
+    READ [message-number]
+
+The message's relative number is found by the DIRECTORY command.  If you
+specify  a number greater than the number of messages in the folder, the
+last message in the folder will be displayed. 
+
+NOTE: The READ command can be abbreviated by omitting the READ  command,
+i.e.  typing  the  command  "2"  is  equivalent  to "READ 2", and simply
+hitting the <RETURN> key is equivalent to "READ". 
+
+BULLETIN normally stores only the latest message that has been read  per
+folder.  It  can  optionally  store and display which messages have been
+read in a folder on a per message basis.  For information on  this,  see
+the help on the SEEN command.
+2 /ALL
+Specifies to read all messages.  Used after /MARKED, /UNMARKED, /SEEN,
+or /UNSEEN had been specified.
+2 /EDIT
+Specifies that the editor is to be used to read the message.  This is
+useful for scanning a long message.
+2 /HEADER
+ /[NO]HEADER
+
+Specifies that if a message header exists, the header will be shown.  If
+/HEADER  or  /NOHEADER  is  specified,  the  setting  will apply for all
+further reads in the selected folder.  The default is /HEADER  for  non-
+NEWS  folders,  /NOHEADER for NEWS folders.  If the SET STRIP command is
+set for the folder, it will change the default to be /HEADER.    A  user
+can  make this option the default for a particular folder or news group.
+See HELP Customizing. 
+2 /MARKED
+Specifies to read only messages that have been marked (marked messages
+are indicated by an asterisk).  Using /MARKED is equivalent to
+selecting the folder with /MARKED, i.e. only marked messages will be
+shown and be able to be read.   To see all messages, use either /ALL,
+or reselect the folder. 
+2 /UNMARKED
+Specifies to read only messages that have not been marked (marked
+messages are indicated by an asterisk).  Using /UNMARKED is equivalent
+to selecting the folder with /UNMARKED, i.e. only unmarked messages
+will be shown and be able to be read.  To see all messages, either
+reselect the folder or specify /ALL.
+2 /ROTATE
+Specifies to decode the message using ROT-13 coding.
+2 /SEEN
+Specifies to read only messages that have been seen (indicated by a
+greater than sign). Using /SEEN is equivalent to selecting the folder
+with /SEEN, i.e. only seen messages will be shown and be able to be
+read.  To see all messages, use either /ALL, or reselect the folder. 
+2 /UNSEEN
+Specifies to read only messages that have not been seen (seen message
+are indicated by a greater than sign). Using /UNSEEN is equivalent to
+selecting the folder with /UNSEEN, i.e. only unseen messages will be
+shown and be able to be read.  To see all messages, use either /ALL, or
+reselect the folder. 
+2 /THREADS
+Reads all messages that have been included by the THREAD  command.    If
+neither  message  number nor /SINCE is specified, the search starts with
+the first new message.  After the  first  READ/THREADS  command,  typing
+READ/THREADS will continue the search from where it left off (as long as
+you do not select a different folder or news  group).    Also,  after  a
+message has been fully read, if the return key is hit without entering a
+command, it is equivalent to typing the READ/THREADS command.   Messages
+which  are  parts  of  threads  and  under read will be displayed in the
+directory listing by a preceeding #. 
+2 /NEW
+Specifies to read the first unread message.
+2 /PAGE
+ /[NO]PAGE
+
+Specifies that the display of the message will pause when it reaches the
+end of the page.  If /NOPAGE is specified, the whole message will be
+displayed.  This is useful for terminals that can store more than one
+screenful at a time, and that have a remote printer that can then print
+the contents of the terminal's memory.
+2 /SINCE
+ /SINCE=date
+
+Specifies to read the first message created on or after the specified
+date.  If no date is specified, the default is TODAY.
+1 REMOVE
+Removes a folder.  Only the owner of a folder or a privileged  user  can
+remove the folder.
+
+  Format:
+    REMOVE folder-name
+1 REPLY
+Adds message with subject of message being the subject of the  currently
+read message with "RE:" preceeding it.  Format and qualifiers is exactly
+the same as the ADD command except for /INDENT and /EXTRACT.
+
+  Format:
+    REPLY [file-name]
+2 /EXTRACT
+Specifies that the text of the message should be included in the reply
+mail message.  This qualifier is valid only when used with /EDIT.  The
+text of the message is indented with -> at the beginning of each line.
+This can be suppressed or the indentation character changed using 
+the qualifer /[NO]INDENT.
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+1 RESET
+Resets the new message counter for the selected folder  or  news  group.
+The  new  message counter stores the latest read message, and is used to
+determine if there are new messages to be read. 
+
+  Format:
+    RESET [message-number]
+
+If no number is specified, the last message in used.    This  is  useful
+when  you  want to simply ignore any new messages without having to read
+them.  (Note: Reading the last message does the same  thing,  but  RESET
+does it without having to read it.)
+2 /CURRENT
+Resets the new message counter to the current message.
+1 RESPOND
+Invokes the VAX/VMS Personal Mail Utility (MAIL) to send a reply mail
+message to the owner of the currently read message.
+
+  Format:
+    RESPOND [file-name]
+
+If you wish to use another method for sending the mail, define BULL_MAILER
+to point to a command procedure.  This procedure will then be executed in
+place of MAIL, and the parameters passed to it are the username and subject
+of the message.
+2 /CC
+ /CC=user[s]
+Specifies additional users that should receive the reply.
+2 /EDIT
+Specifies that the editor is to be used for creating the reply mail
+message.
+2 /EXTRACT
+Specifies that the text of the message should be included in  the  reply
+mail  message.   This qualifier is valid only when used with /EDIT.  The
+text of the message is indented with -> at the beginning of  each  line.
+This  can  be  suppressed or the indentation character changed using the
+qualifer /[NO]INDENT. 
+2 /GROUPS
+ /GROUPS=(newsgroup,[...])
+
+Valid only if a NEWS group is selected or /LIST is present.    Specifies
+to  send  the  message to the specified NEWS group(s) in addition to the
+selected NEWS group. 
+2 /LIST
+Specifies that the reply should also be sent to the network mailing list
+associated  with  the folder.  The mailing list address should be stored
+in the folder description.  See CREATE/DESCRIPTION or MODIFY/DESCRIPTION
+for more informaton. 
+2 /INDENT
+ /[NO]INDENT=string
+
+See /EXTRACT for information on this qualifier.
+2 /NOSIGNATURE
+Specifies to suppress  the  automatically  appended  signature,  if  one
+exists.    Signatures  are appended for postings to mailing lists and to
+responds.    See  the  help  topic  POST  Signature_file  for  signature
+information. 
+2 /SUBJECT
+ /SUBJECT=text
+
+Specifies the subject of the mail message. If the text consists of  more
+than one word, enclose the text in quotation marks ("). 
+
+If you omit this qualifier, the description of the message will be  used
+as the subject preceeded by "RE: ". 
+1 SEARCH
+Searches the currently selected folder for the  message  containing  the
+first occurrence of the specified text strings.
+
+   Format:
+
+       SEARCH [search-string[,...]]
+
+The search starts from the first message in the current folder.  You can
+specify  the message to start at using the qualifier /START.  If you use
+this qualifier without a parameter, it starts with the current  message.
+The  search  includes  both the text of the message, and the description
+header.  If a "search-string" is not specified, a search is  made  using
+the previously specified string, starting with the message following the
+one you are currently reading (or have just read).  After fully  reading
+the  message  found  by  the  search,  if you hit the return key without
+entering a command, it is equivlanent to typing SEARCH without a  search
+string and will search for the next message.  Once started, a search can
+be aborted by typing a CTRL-C. 
+2 /EDIT
+Specifies that the editor is to be used for reading the message.
+2 /FEEDBACK
+Used only in conjunction with /FOLDER and /GROUP.    Specifies  to  show
+when new folders or news groups are selected. 
+2 /FOLDER
+   /FOLDER=(folder,[...])
+
+Specifies a list of folders to be searched.  The search  will  start  by
+selecting  the first folder in the list and searching the messages for a
+match.  If, during a search, no more matches or messages are found,  the
+next  folder  in  the  list  is  automatically  selected.  The presently
+selected folder can be included in the search by specifying  ""  as  the
+first  folder  in  the  list.    Use  /FEEDBACK  to see when folders are
+selected.  News groups can be specified here.  However, to search news
+group with wild cards, use /GROUP.
+2 /GROUP
+   /GROUP=(string,[...])
+
+Specifies a list of groups to be searched.  Wildcards are  permitted  in
+the specified string.  	If the string does not contain an * and does not
+specify a news group, * is automatically placed at the beginning and end
+of  the  string.    I.e.  if  the string is "comp", then all news groups
+containing the word "comp" will be searched.  Use /FEEDBACK to see  when
+groups are selected.
+2 /FROM
+Specifies that only the username of the messages are to be searched.
+2 /MATCH
+ /MATCH[=option]
+
+Interprets and matches multiple search strings in one of  the  following
+ways: 
+
+     AND      A match occurs only if all of the strings are found.
+
+     OR       A match occurs if any of the strings are found.
+
+     XOR      A match occurs if only one of the strings is found.
+
+If you specify none of these options, the default is /MATCH=OR.  If  you
+specify the /NEGATED qualifier, you will get the negated operation. 
+2 /NEGATED
+If specified, messages that don't match the specified search string
+command are displayed.  Does not work with /NOREPLIES.
+2 /NOREPLIES
+Specifies to find messages which are not replies (i.e. whose subject
+do not start with RE:).
+2 /REPLY
+Specifies that messages are to be searched for that are replies  to  the
+currently read message, or the message specified by /START.  Replies are
+messages which have subject of the original message prefaced by "Re:". 
+2 /REVERSE
+Specifies that the messages are to be searched in reverse order.  If  no
+starting  message  is  specified,  the  search  is started from the last
+message.  /REVERSE must be specified with a search string.
+2 /START
+ /START=message_number
+
+Specifies the message number to start the search at.  If  you  omit  the
+message number, it starts with the current message. 
+2 /SUBJECT
+Specifies that only the subject of the messages are to be searched.
+1 SEEN
+Sets the current or message-id message as seen. This allows you to keep
+track of messages on a per message basis.  Seen messages are displayed
+with a greater than sign in the left hand column of the directory
+listing.  Once you have used the SEEN command once, messages will be
+automatically be set as being SEEN when they are read.  The UNSEEN
+command sets the current or message-id message as unseen. 
+
+   Format:
+
+       SEEN [message-number or numbers]
+       UNSEEN [message-number or numbers]
+
+Keeping track of seen messages requires very little overhead for NEWS
+folders.  However, there is a moderate overhead for regular non-NEWS
+folders.  If you have used the SEEN command and wish to disable the
+automatic marking of messages in regular folders as SEEN when they are
+read, type the command SEEN/NOREAD.  To reenable, simply use the SEEN
+command again. 
+
+If a specified message is newer than the newest read message, then the
+newest read message counter will be updated.  The newest read message 
+counter is used to determine if there are new messages to be read.
+You are alerted of this when entering BULLETIN or selecting a folder
+or news group.  If you simply want to reset this counter and don't care
+about marking which messages have been seen or not, use the RESET command.
+
+NOTE: The list of SEEN messages for non-NEWS folders are stored in a
+file username.BULLMARK, and NEWS folders are stored in
+username.NEWSMARK. The files are created in the directory pointed to by
+the logical name BULL_MARK.  If BULL_MARK is not defined, SYS$LOGIN
+will be used. 
+1 SELECT
+Selects a folder of messages.  See HELP Folders for a description  of  a
+folder.   Once a folder has been selected, all commands, i.e. DIRECTORY,
+READ, etc. will apply only to those messages.  Use the CREATE command to
+create  a  folder.   Use the DIRECTORY/FOLDER command to see the list of
+folders that have been created.
+
+ Format:
+
+     SELECT [node-name::][folder-name]
+
+The complete folder name need not be specified.  BULLETIN  will  try  to
+find the closest matching name.  I.e. INFOV can be used for INFOVAX.
+
+Omitting the folder name will select the default folder.
+
+The  node  name can be specified only if the remote node has the special
+BULLCP process running (invoked by BULLETIN/STARTUP command.)
+
+After selecting a folder, the user will notified of the number of unread
+messages,  and  the  message  pointer will be placed at the first unread
+message.
+
+BULLETIN automatically determines if the selcted name is a NEWS group by
+detecting if a period is present in the name being  specified,  as  most
+NEWS  groups  contain  a  period,  whereas  a real folder cannot.  A few
+special NEWS groups, i.e. JUNK and CONTROL, do not contain a period.  If
+desired,  you can select these groups by enclosing them in double quotes
+("), and typing the name in lower case.
+
+A useful way to scan through folders or subscribed news group without 
+having to select them manually is to use the INDEX command.
+2 /MARKED
+Selects  only messages that have been marked (indicated by an asterisk).
+After using /MARKED, in order to see all messages, the folder will  have
+to be reselected.
+2 /UNMARKED
+Specifies to read only messages that have not been marked (marked
+messages are indicated by an asterisk).  
+
+After using, in order to see all messages, the folder will  have
+to be reselected.
+2 /SEEN
+Specifies to read only messages that have been seen (indicated by a
+greater than sign).
+
+After using, in order to see all messages, the folder will  have
+to be reselected.
+2 /UNSEEN
+Specifies to read only messages that have not been seen (seen message
+are indicated by a greater than sign).
+
+After using, in order to see all messages, the folder will  have
+to be reselected.
+1 SET
+The SET command  is  used  with  other  commands  to  define  or  change
+characteristics of the BULLETIN Utility.
+
+  Format:
+
+    SET option
+2 ACCESS
+Controls  access  to  a  private  folder.   A private folder can only be
+selected by users who have been granted access.  Only the owner of  that
+folder is allowed to grant access.
+
+  Format:
+
+    SET [NO]ACCESS id-name [folder-name]
+
+The id-name can be one or more ids from the system Rights  Database  for
+which  access  is  being  modified.   It  can  also be a file name which
+contains a list of  ids.   For  more  information  concerning  usage  of
+private  folders, see HELP CREATE /PRIVATE.  NOTE: Access is created via
+ACLs.  If a user's process privileges are set  to  override  ACLs,  that
+user  will  be  able  to  access  the folder even if access has not been
+granted.
+
+It  is suggested that if you plan on granting access to many users, that
+you create an id using the AUTHORIZE utility and then use the SET ACCESS
+command  to  grant  access  to  that id.  Then, you can use the GRANT/ID
+command in AUTHORIZE to grant the id to users, and this will give  those
+users  access to the folder.  This is preferred because of problems with
+running into system quota when checking for acls on a file with a  large
+amount  of  acls.   It  is also means that you don't have to remember to
+remove the access for that user from a folder if that  user  is  removed
+from the system.
+
+A user with BULLETIN privileges (see HELP SET  PRIV)  will  be  able  to
+select a protected folder regardless of the access settings.  However, a
+user without explicit access will not receive login notifications of new
+messages,  and thus will not be able to set any login flags.  (NOTE:  If
+such a user selects such a folder and then uses SET ACCESS to grant  him
+or  herself  access,  the user must reselect the folder in order for the
+new access to take affect in order to be able to set login flags.)
+3 id
+The id-name can be one or  more  ids  contained  in  the  system  Rights
+Database.    This  includes  usernames  and  UICs.    UICs  can  contain
+wildcards, i.e.  [130,*].  Note that by default, a process is given  the
+process  rights  id  SYS$NODE_nodename,  where  nodename  is  the decnet
+nodename.  Thus, by specifing this id, a folder can be restricted  to  a
+specific  node, which is useful when the folder is shared among nodes in
+a cluster. 
+
+Alternatively,  the  id-name  can be a filename which contains a list of
+ids.  The filename should be preceeded by a "@".  If the suffix  is  not
+specified, it will be assumed that the suffix is ".DIS" .
+3 /ALL
+Specifies that access to the folder is granted to all users.   If  /READ
+is  not  specified,  the  folder will no longer be private.  If /READ is
+specified, all users will have read access, but  only  privileged  users
+will  have  write access (of course non-privileged users can gain access
+via a later SET ACCESS command.)
+
+Format:
+
+    SET ACCESS /ALL [folder-name]
+3 /CLASS
+Specifies that the specified folder is a news group class.
+3 /READ
+Specifies that access to the folder will be limited to being able to
+read the messages.
+3 Warning
+If  a  user  logs  in after a private folder has been created but before
+being given access, and then is given  access,  any  defaults  that  the
+folder  has,  i.e. /BRIEF, /READNEW, & /NOTIFY, will not be set for that
+user. This is because if the  id  is  not  a  username,  it  becomes  an
+extremely  lengthy  operation  to check each user to see if have that id
+assigned to them.  The alternative is to set the defaults for all  users
+after  every  SET  ACCESS,  but that might cause problems with users who
+have manually reset those defaults.  The  correct  solution  requires  a
+large programming modification, which will be done in a later version.
+2 ANONYMOUS
+Specifies that the selected folder has the ANONYMOUS  attribute.    This
+causes  messages  in  the  folder  to  be  displayed  with  the username
+ANONYMOUS rather than the actual user's name.
+
+  Format:
+
+    SET [NO]ANONYMOUS
+2 ALWAYS
+Specifies  that  the  selected  folder  has  the ALWAYS attribute.  This
+causes messages in the folder to be displayed differently  when  logging
+in.  SYSTEM messages will be displayed every time a user logs in, rather
+than just once.  Non-SYSTEM message will also be  displayed  every  time
+(in  whatever  mode  is selected, i.e. BRIEF, SHOWNEW, or READNEW) until
+the user actually reads that message (or a later one).  This feature  is
+meant  for  messages which are very important, and thus you want to make
+sure they are read.
+
+  Format:
+
+    SET [NO]ALWAYS
+2 ADD_ONLY
+Specifies that the selected folder  has  the  ADD_ONLY  attribute.    If
+ADD_ONLY  is  set  and  a mailing address is present (see /DESCRIPTION),
+when a message is added to the folder, it will also  be  mailed  to  the
+address  (in addition to being stored in the folder).  This also applies
+to a message which is added via the BBOARD feature .  If ADD_ONLY is set
+and  a user uses the POST command, the ADD command will be used instead.
+One use for this is to mail messages in a folder to  users  who  do  not
+have access to BULLETIN. 
+
+  Format:
+
+    SET [NO]ADD_ONLY
+2 BBOARD
+Specifies  a username to be used as a BBOARD destination.  Mail which is
+sent to that user are converted into messages.  This command will  apply
+to  the  selected folder, and each folder can have its own BBOARD.  Only
+privileged users or owners of the folders can  set  BBOARD.   Note:  The
+specified  account  must  have  the DISUSER flag specified in the system
+authorization file, and it either must be given  SYSPRV  privileges,  or
+the  scratch  bboard_directory  (specified when compiling BULLETIN) must
+have world rwed  protection.   Also,  certain  system  parameters  which
+affect  detached  subprocesses  are  usually  too low for the subprocess
+which is spawned to read the mail.  The  parameters  and  the  suggested
+values  are:  PQL_DPGFLQUOTA = 15000, PQL_DWSQUOTA = 500, and PQL_DFILLM
+= 30.  If you are not using the BULLCP process, the subprocess limit for
+users must be at least 2.
+
+  Format:
+
+    SET BBOARD [username]
+
+BBOARD cannot be set for remote folders.   See  also  the  commands  SET
+STRIP and SET DIGEST for options on formatting BBOARD messages.
+
+If BULLCP is running, BBOARD is updated every 15 minutes.  If you want
+to length this period, define BULL_BBOARD_UPDATE to be the number of
+minutes, between updates.  I.e. DEFINE/SYSTEM BULL_BBOARD_UPDATE "30"
+will cause the updates to be don every 30 minutes.
+
+NOTE: If you want to control the expiration date on a per message basis,
+you can do so by adding a special header line to the message.  The form
+is Expires: or X-Expires: followed by the date in the form DD MMM YYYY.
+The time will always be 00:00, even if the time is specified on the line.
+3 /EXPIRATION
+ /EXPIRATION=days
+ /NOEXPIRATION
+
+Specifies the number of days the message created by the BBOARD is to  be
+retained.   The  default  is  14  days.   The  highest limit that can be
+specified is 30 days.  This can be overridden by a user with privileges.
+If /NOEXPIRATION is specified, messages will become permanent.
+
+NOTE:  This  value is the same value as specified by SET DEFAULT_EXPIRE.
+If one is changed, the other will change also.
+3 /SPECIAL
+Specifies that the input should be processed  using  a  special  command
+procedure,  and  not  to  use the simple VMS MAIL to message conversion.
+Specifying a username is optional.  To remove  this  feature,  you  must
+either  SET  NOBBOARD,  or  SET  BBOARD  and  specify  a  username.  See
+installation notes for exactly how to use this feature.
+3 /VMSMAIL
+Used in conjunction with  /SPECIAL.   If  /SPECIAL  and  a  username  is
+specified,  and the conversion still takes its input from VMS MAIL, then
+the VMS system mail file is checked to see if new mail  exists  for  the
+specified  user  before  running the command procedure.  This saves time
+and avoids creating subprocesses.  (Useful if input is digest format.)
+3 Listserv
+For a LISTSERV mailing list, only a subscribed user can post to it.   If
+the  BBOARD  account  is subscribed to the list in order for BULLETIN to
+receive the list, only the BBOARD account will be able to  post  to  it.
+This  problem  is  solved  by  placing  the  word LISTSERV in the folder
+description line. Then, messages sent to the mailing list  by  the  POST
+command will be sent from the BBOARD account rather than from the user's
+account.  For example, the folder description might be:
+
+FAKE MAILING LIST <FAKELIST@FAKENODE.BITNET> LISTSERV.
+
+If  you  have  PMDF  or  MX  installed,  the  corresponding logical name
+PMDF_REPLY_TO or MX_REPLY_TO will be temporarily defined in order to add
+a  REPLY-TO:   line  to  the  message  header to display the real user's
+address.
+
+Users  who  use the method described in HELP SET BBOARD MORE_INFORMATION
+should note the following:  When using this LISTSERV feature, the BBOARD
+account  must be a real account, not simply a VMS MAIL forwarding entry.
+Mail can only be sent from a real account.  However, if mail  forwarding
+is  set for that the account, the account does not need a real directory
+or a unique uic, since it will not need space to store mail.
+
+In order to be able to send LISTSERV commands from  the  BBOARD  account
+without  having  to  actually  login  to  the BBOARD account, there is a
+utility included with BULLETIN called SETUSER.  This requires privileges
+to use.  After compiling it, use the link command:
+
+        LINK SETUSER,SYS$SYSTEM:SYS.STB/SELECT
+
+When  you  run  it, it will prompt for a username.  After verifying that
+the given username  is  a  valid  account,  it  will  then  change  your
+process's username.  You can then send mail from that account.
+
+If you are using PMDF or MX, and wish to use this feature, you can still
+do  so  by  setting BBOARD.  As long as the BBOARD account is not a real
+account, it will work properly, even though the mail feed is not  really
+coming from the BBOARD account.
+
+In order to find out if the LISTSERV mailing list will accept posts only
+from subscribed users, send  the  command  'REV  listname'.   This  will
+retrieve the file listname.LIST.  It begins with a list of keywords.  If
+the keyword 'send' is set  to  'public',  you  don't  need  to  set  the
+LISTSERV  switch.   If it's set to 'private', you do.  For a description
+of the keywords and the meaning of their settings, send any LISTSERV the
+command  'INFO  KEY'. Note that the 'listname.LIST' files include a list
+of owners and subscribers.  If 'send' is set to 'owners',  then  neither
+the public nor the subscribers can post to the list.
+
+Note: It has been found that some servers don't accept the mail as being
+from the bboard account if the reply-to: line is added.  This might be
+due to it being run on VMS, where the Reply-to: line is converted to the
+From: line.  In this case, specify VMSSERV instead of LISTSERV.
+3 More_information
+If more than one folder is to have a BBOARD setting,  only  one  of  the
+BBOARD  names  need  be  a real account.  All other names could be names
+whose mail is  forwarded  to  the  real  account.   BULLETIN  will  then
+determine  from  the mail header which folder the mail is to be sent to.
+Forwarding can be enabled for any name within MAIL by the command:
+
+    MAIL> SET FORWARD/USER=from_name to_name
+
+Any  mail  sent  to  FROM_NAME will be forwarded to TO_NAME.  Thus, only
+TO_NAME need be a real account.  For example, if you  have  INFOVAX  and
+LASER-LOVERS  folders,  you need create only a INFOVAX account, and then
+forward LASER-LOVERS mail to INFOVAX within mail using the  command  SET
+FORWARD/USER=LASER-LOVERS  INFOVAX.   You  would  then  do  a SET BBOARD
+INFOVAX for the INFOVAX folder, and  SET  BBOARD  LASER-LOVERS  for  the
+LASER-LOVERS  folder.   This method will speed up the BBOARD conversion,
+since mail need be read only from one account.  NOTE: Folders that  have
+the  /SPECIAL  set  on  their  BBOARD  accounts  cannot  have their mail
+forwarded to BBOARD accounts that don't have /SPECIAL set.   Folders  of
+the  same  type, i.e. that use the same /SPECIAL command procedure, must
+be grouped separately.
+
+The BBOARD account must match the mailing list name.  If you prefer  not
+to  have  them  match,  then  you must include the actual address of the
+mailing list in the folder description in  the  format  described  under
+HELP CREATE /DESCRIPTION.
+2 BRIEF
+Controls whether you will be alerted upon logging  that  there  are  new
+messages  in the currently selected folder.  A new message is defined as
+one that has been created since the last time you logged in or  accessed
+BULLETIN.   Note  the  difference between BRIEF and READNEW.  The latter
+causes a listing of the description of the new messages to be  displayed
+and  prompts  the user to read the messages.  Setting BRIEF will clear a
+READNEW setting (and visa versa).
+
+  Format:
+
+    SET [NO]BRIEF
+3 /ALL
+Specifies that the SET [NO]BRIEF option is the default for all users for
+the specified folder.  This is a privileged qualifier.
+3 /DEFAULT
+Specifies that the [NO]BRIEF option is the default for the specified
+folder.  This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).  Use /ALL to modify all users.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the option is to modified.  If not
+specified, the selected folder is modified. Valid only with NOBRIEF.
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that BRIEF is a permanent flag and cannot be changed by the
+individual, except if changing to SHOWNEW or READNEW.  This is a
+privileged qualifier.
+2 COMPRESS
+Specifies that messages added to the folder will be in compressed format.
+Data stored in this way will be 60-65% the size of normal folders.
+The compression algorithm is optimized for English text files and requires 
+very little cpu overhead.
+
+  Format:
+
+    SET [NO]COMPRESS
+
+This command is only valid with folders.  Local news groups are always
+stored in compressed format.  Messages already stored in the folder 
+can not presently be changed to compressed format. 
+2 CONTINUOUS_BRIEF
+Specifies that if BRIEF is set for a folder, and there are new messages,
+the notification message "there are new messages" will be displayed every
+time when logging in, until the new messages are read.  Normally, the
+BRIEF setting causes notification only at the first time that new messages
+are detected.
+
+  Format:
+
+    SET [NO]CONTINUOUS_BRIEF
+
+NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the
+same user.
+2 DEFAULT_EXPIRE
+Specifies  the  number  of days the message created by BBOARD (or direct
+PMDF path) is to be retained.  The default  is  14  days.   The  highest
+limit  that  can  be  specified is 30 days.  This can be overridden by a
+user with privileges.
+
+This  also  specifies the default expiration date when adding a message.
+If no expiration date is  entered  when  prompted  for  a  date,  or  if
+prompting  has been disabled via SET NOPROMPT_EXPIRE, this value will be
+used.
+
+  Format:
+
+    SET DEFAULT_EXPIRE days
+
+If -1 is specified, messages will become permanent.  If 0 is  specified,
+no  default expiration date will be present.  The latter should never be
+specified for a  folder  with  a  BBOARD,  or  else  the  messages  will
+disappear.
+
+NOTE: This value is the same value that SET BBOARD/EXPIRATION specifies.
+If one is changed, the other will change also.
+2 DIGEST
+Affect  only  messages  which are added via either the BBOARD option, or
+written directly from a network mailing program  (i.e.  PMDF).   Several
+mailing  lists  use  digest  format  to  send  their  messages, i.e. the
+messages are concatenated into one long message.  If DIGEST is set,  the
+messages will be separated into individual BULLETIN messages.
+
+  Format:
+
+    SET [NO]DIGEST
+
+The command SHOW FOLDER/FULL will show if DIGEST has been set.
+
+2 DUMP
+Specifies that messages deleted from the  selected  folder  are  written
+into  a dump (or log) file.  The name of the log file is foldername.LOG,
+and it is located in the folder directory (usually BULL_DIR).
+
+  Format:
+
+    SET [NO]DUMP
+
+The command SHOW FOLDER/FULL will show if dump has  been  set.    (NOTE:
+SHOW  FOLDER/FULL  is a privileged command.) When created, the file will
+have an ACL set on it to allow the folder owner to delete it.
+2 EXPIRE_LIMIT
+Specifies expiration limit that is allowed for messages.  Non-privileged
+users cannot specify an expiration  that  exceeds  the  number  of  days
+specified.  Privileged users can exceed the limit.
+
+  Format:
+
+    SET [NO]EXPIRE_LIMIT [days]
+
+The command SHOW FOLDER/FULL will show  the  expiration  limit,  if  one
+exists.  (NOTE: SHOW FOLDER/FULL is a privileged command.) 
+2 EXCLUDE
+Specifies to ignore any EXCLUDEs or THREADs that are present.
+
+  Format:
+
+    SET [NO]EXCLUDE
+
+The default mode is SET EXCLUDE, which means to display  messages  based
+on  specified  EXCLUDEs  or  THREADs.    SET  NOEXCLUDE  will cause all
+messages to be displayed for the selected folder, and all future folders
+which are selected. 
+2 EXLIMIT
+Specifies the default limit for the EXCLUDE command. 
+
+  Format:
+
+    SET EXLIMIT days
+
+If no match is found for an exclude after the specified number of  days,
+the  exclude  will  automatically  be deleted.  The default is no limit,
+which is specified by specifying 0 days.  This default can be  overriden
+by the /LIMIT switch on the EXCLUDE command. 
+2 FILE_DIRECTORY
+Select the directory where  messages  are  written  to  when  using  the
+EXTRACT  or  file  COMMAND.  By default, the message is written into the
+current directory. 
+
+  Format:
+
+    SET FILE_DIRECTORY [directory]
+
+If directory is omitted, the setting is removed.  Note: This information
+is stored in the customization file (SYS$LOGIN:BULL.CUSTOM).
+2 FOLDER
+Select a folder of messages.  Identical to the SELECT command.  See help
+on that command for more information.
+
+  Format:
+
+    SET FOLDER [node-name::][folder-name]
+3 /MARKED
+Selects messages that have been marked (indicated by an asterisk).
+After using /MARKED, in order to see all messages, the folder will have
+to be reselected.
+2 GENERIC
+Specifies  that  the  given  account is a "generic" account, i.e used by
+many different people.  If an  account  is  specified  as  GENERIC,  new
+messages  placed in the default folder will be displayed upon logging in
+for a specific number of days,  rather  than  only  once.   The  default
+period is 7 days.  This command is a privileged command.
+
+  Format:
+
+    SET [NO]GENERIC username
+
+NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the
+same user.
+3 /DAYS
+ /DAYS=number_of_days
+
+Specifies the number days that new messages will be displayed for upon
+logging in.
+2 GATEWAY
+Valid for folders that are associated with an email address.    Messages
+which  are  mailed  to the email address are by default modified so that
+the subject line starts with the folder name,  followed  by  the  phrase
+"folder  message:  ",  followed  original  subject line.  If you specify
+GATEWAY, the subject line is not modified this way. 
+2 KEYPAD 
+Controls whether the keypad has been enabled such that the keys  on  the
+keypad correspond to command definitions.  These definitions can be seen
+via the SHOW KEYPAD command.  The default is NOKEYPAD unless the /KEYPAD
+qualifier has been added to the BULLETIN command line.
+
+  Format:
+
+    SET [NO]KEYPAD
+
+The default settings  for the keypad are shown via SHOW KEYPAD or HELP
+KEYPAD.  Settings can be  changed by using an initialization file with
+DEFINE/KEY commands.  BULLETIN looks first for the file pointed to by
+the logical name BULL_INIT and  then for the file SYS$LOGIN:BULL.INI.
+2 LIBRARY
+Specifies a library of folders.  By default there is only  one  library.
+However,  the system manager may decide to create more than one library,
+with each library  saved  in  a  different  directory.    Use  the  SHOW
+LIBRARY/ALL command to see if there are other libraries. 
+2 LOGIN
+Controls  whether  the  specified  user will be alerted of any messages,
+whether system or non-system, upon logging in.  If an  account  has  the
+DISMAIL  flag  set, SET NOLOGIN is automatically applied to that account
+during the first time that the account logs in.  However, this will  not
+occur  if DISMAIL is set for an old account.  Additionally, removing the
+DISMAIL flag will not automatically enable LOGIN.  (The reason  for  the
+above  was to avoid extra overhead for constant checking for the DISMAIL
+flag.)  This command is a privileged command.
+
+  Format:
+
+    SET [NO]LOGIN username
+2 NAME
+Copies all stored settings from one user to another.  Used when a user's
+account name is changed.
+
+  Format:
+
+    SET NAME old-username new-username
+2 NEWS
+Changes attributes of the specified news group or class of news groups.
+This command requires privileges.
+
+  Format:
+
+    SET NEWS [news-group]
+
+If no attributes are specified, the present values of the attributes are
+shown.
+3 /ALL
+   /ALL
+   /NOALL
+
+If specified with /CLASS or /DEFAULT, all groups that are presently
+available will have their attributes changed,in addition to any that are
+created in the future.  If /NOALL is specified, the attributes of any
+news group that was individually changed will not be modified.  I.e., if
+you set the attributes for misc.test, and then change the default
+attributes (using /DEFAULT) with /NOALL, the attributes for misc.test
+will not be changed.  This also applies when specifying the attributes
+for a class of news groups with /CLASS, but only if the value for /CLASS
+is a primary class, i.e. it has a no period in the classname such as
+CLASS=rec.  Otherwise, /NOALL is not allowed with /CLASS.  The default
+is /ALL.                                     
+3 /CLASS
+   /CLASS=classname
+
+Specifies to modify attributes for a class of news groups rather than a
+single group, i.e. /CLASS=rec, or /CLASS=sci.med .  Attributes of
+existing groups which are in the class are modified, and any groups
+created in the future will automatically have those attributes.
+3 /DEFAULT
+Specifies default attributes which are applied to all news groups.
+3 /DELETE
+When used with /CLASS, specifies that the class attributes are to be
+deleted.
+3 /DISABLE
+Specifies that the news group is disabled and can not be accessed.
+3 /ENABLE
+Specifies that the news group is enabled and can be accessed. This is
+the default.
+3 /EXPIRATION
+   /EXPIRATION=days
+
+Specifies the default expiration time for messages if none is specified.
+The default is 7.
+3 /FULL
+Control whether all information of the news groups  is  displayed,  i.e.
+the  access list if the news group is private.  This information is only
+those who have access to that folder. 
+3 /LIMIT
+   /LIMIT=days
+
+Specifies the expiration limit for messages.  If the value specified is
+-1, there will be no limit.  If the value is 0, the default limit will
+be applied, or of any class that is applicable.  This is the default.
+It is suggested that the limit be set a no lower than 31 days, as many
+groups have a FAQ (frequently asked question) message which is posted
+every month with an expiration date of one month in the future.
+3 /PRIVATE
+   /PRIVATE
+   /NOPRIVATE
+
+Specifies that the news group or class can have it's access modified by
+the SET ACCESS command.  To accomplish this, a file is created in
+NEWS_DIRECTORY specified in BULLFILES.INC and ACLs are set on that file.  
+Note:  If you set access for a class, the best way to grant all access 
+to news groups in that class is to set /NOPRIVATE, as then time won't be 
+wasted checking a file for ACLs.
+3 /STORED
+   /STORED
+   /NOSTORED
+
+Specifies that the news group are stored on disk rather then accessed
+via the network from the server node.  This results in faster access,
+but requires the available disk space.  Messages from the news group
+are not immediately transferred as the result of this command, but are
+tranferred by the separate BULLCP process at regular intervals.  The
+default is /NOSTORED.
+2 NODE
+Modifies the selected folder from a local folder to a remote folder.   A
+remote folder is a folder in which the messages are actually stored on a
+folder at a remote DECNET node.  The SET NODE command specifies the name
+of  the  remote  node, and optionally the name of the remote folder.  If
+the remote folder name is not included, it is assumed to be the same  as
+the  local  folder.   When  the command is executed, the selected folder
+will then point to the remote folder.  If there  were  messages  in  the
+local folder, they will be deleted.  This feature is present only if the
+BULLCP process is running on the remote node.
+
+  Format:
+    SET NODE nodename [remotename]
+    SET NONODE
+
+NOTE: If one node adds a message to a remote node, other nodes connected
+to the same folder will not immediately be aware  of  the  new  message.
+This  info  is  updated  every  15  minutes,  or if a user accesses that
+folder.
+
+If you are using V2.16 or greater on both nodes, then if the data files 
+of the node containing the remote folder are moved to a different node,
+(or if you decided to start BULLCP on a different nooe in that cluster),
+the nodename of the remote folders will automatically be updated.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the node information is to modified.
+If not specified, the selected folder is modified.
+2 NOTIFY
+Specifies whether you will be notified via a broadcast  message  when  a
+message is added to the selected folder.
+
+  Format:
+
+    SET [NO]NOTIFY
+
+In a cluster, if the logical name MAIL$SYSTEM_FLAGS is defined so that
+bit 1 is set, users will be notified no matter which node they are logged
+in to.  If you wish to disable this, you should define BULL_SYSTEM_FLAGS
+so that bit 1 is cleared.
+3 /ALL
+Specifies that the SET [NO]NOTIFY option is the default for all users for
+the specified folder.  This is a privileged qualifier.
+3 /DEFAULT
+Specifies that the [NO]NOTIFY option is the default for the specified
+folder.  This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).  Use /ALL to modify all users.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the option is to modified.  If not
+specified, the selected folder is modified. Valid only with NONOTIFY.
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that NOTIFY is a permanent flag and cannot be changed by the
+individual. /DEFAULT must be specified. This is a privileged qualifier.
+2 PAGE
+Specifies whether any directory listing or message reading  output  will
+pause  when  it  reaches  the end of the page or not.  Setting NOPAGE is
+useful for terminals that can store more than one screenful at  a  time,
+and  that  have a remote printer that can then print the contents of the
+terminal's memory.  The default is PAGE, unless the default was  changed
+by specifying /NOPAGE on the command line to invoke BULLETIN.
+
+  Format:
+
+    SET [NO]PAGE
+2 POST_ONLY
+Specifies that the selected folder has the POST_ONLY attribute.  This
+causes the ADD command to mail the message to the mailing address if it
+is present (see /DESCRIPTION), rather than add to the folder.  
+
+  Format:
+
+    SET [NO]POST_ONLY
+2 PRIVILEGES
+Specifies  either  process  privileges  or  rights  identifiers that are
+necessary to use privileged commands.  Use the SHOW  PRIVILEGES  command
+to see what is presently set.  This is a privileged command.
+
+  Format:
+
+    SET PRIVILEGES parameters
+
+The parameters are one or  more  privileges  separated  by  commas.   To
+remove  a privilege, specify the privilege preceeded by "NO".  If /ID is
+specified, the parameters are rights identifiers.
+3 /ID
+ /[NO]ID
+
+If specified, then the rights identifier which is specified as the
+parameter will allow users holding that rights identifier to execute
+privileged commands.  If /NOID is specified, the identifier is removed.
+2 PROMPT_EXPIRE
+Specifies  that  a  user  will  be  prompted for an expiration date when
+adding a message.  If NOPROMPT_EXPIRE is specified, the user will not be
+prompted, and the default expiration (which is set by SET DEFAULT_EXPIRE
+or SET BBOARD/EXPIRATION) will be  used.   If  the  value  specified  is
+greater   than  the  expiration  limit,  and  the  user  does  not  have
+privileges, then the expiration  limit  will  be  used  as  the  default
+expiration.  (If there is no expiration limit, and the user doesn't have
+privileges, then an error will result.)  PROMPT_EXPIRE is the default.
+
+  Format:
+
+    SET  [NO]PROMPT_EXPIRE
+2 READNEW
+Controls whether you will be prompted upon logging in  if  you  wish  to
+read new non-system or folder messages (if any exist).  A new message is
+defined as one that has been  added  since  the  last  login,  or  since
+accessing BULLETIN.  The default setting for READNEW is dependent on how
+the folder was created by the owner.
+
+In  order  to  apply  this to a specific folder, first select the folder
+(using the SELECT command), and then enter the SET READNEW command.
+
+  Format:
+
+    SET [NO]READNEW
+
+NOTE:  If  you  have several folders with READNEW enabled, each folder's
+messages will be displayed separately.  However, if you EXIT the READNEW
+mode before all the folders have been displayed, you will not be alerted
+of the new messages in the undisplayed folders the next time you  login.
+However,  if  you enter BULLETIN, you will be told that new messages are
+present in those other folders.  Also, it is not possible  to  EXIT  the
+READNEW mode if there are SYSTEM folders which have new messages. Typing
+the EXIT command will cause you to skip to those folders.  (See HELP SET
+SYSTEM for a description of a SYSTEM folder).
+3 /ALL
+Specifies that the SET [NO]READNEW option is the default for all users for
+the specified folder.  This is a privileged qualifier.  The difference
+between this and /DEFAULT is that the latter will only apply to new users
+(i.e. any users which have never executed BULLETIN).
+3 /DEFAULT
+Specifies that the [NO]READNEW option is the default for the specified
+folder.  This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).  Use /ALL to modify all users.
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the option is to modified.  If not
+specified, the selected folder is modified. Valid only with NOREADNEW.
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that READNEW is a permanent flag and cannot be changed by the
+individual.  This is a privileged qualifier.
+2 SHOWNEW
+Controls whether a directory listing of new  messages  for  the  current
+folder  will  be displayed when logging in.  This is similar to READNEW,
+except you will not be prompted to read the messages.   The  default  is
+dependent  on how the folder was created by the owner.  A new message is
+defined as one that has been  added  since  the  last  login,  or  since
+accessing BULLETIN.
+
+In order to apply this to a specific folder,  first  select  the  folder
+(using  the  SELECT  command),  and  then enter the SET SHOWNEW command.
+
+  Format:
+
+    SET [NO]SHOWNEW
+3 /ALL
+Specifies that the SET [NO]SHOWNEW option is the default for all users for
+the specified folder.  This is a privileged qualifier.  The difference
+between this and /DEFAULT is that the latter will only apply to new users
+(i.e. any users which have never executed BULLETIN).
+3 /DEFAULT
+Specifies that the [NO]SHOWNEW option is the default for  the  specified
+folder.   This is a privileged qualifier.  It will only affect brand new
+users (or those that have never logged in).   Use  /ALL  to  modify  all
+users. 
+3 /FOLDER
+   /FOLDER=foldername
+
+Specifies the folder for which the  option  is  to  modified.    If  not
+specified, the selected folder is modified. Valid only with NOSHOWNEW. 
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that SHOWNEW is a permanent flag and cannot be changed by  the
+individual,  except  if  changing  to  READNEW.  This  is  a  privileged
+qualifier. 
+2 STRIP
+Affect only messages which are added via either the  BBOARD  option,  or
+written  directly  from a network mailing program (i.e. PMDF).  If STRIP
+is set, the header of the mail message will be stripped off before it is
+stored as a BULLETIN message. 
+
+  Format:
+
+    SET [NO]STRIP
+
+The command SHOW FOLDER/FULL will show if STRIP has been set.
+2 SUBSCRIBE
+Can be used to force users to be subscribed to the selected news  group.
+This is a privileged command. 
+
+  Format:
+
+    SET SUBSCRIBE
+
+Note:  If you execute the  commands  SET  SHOWNEW,  READNEW,  BRIEF,  or
+NOTIFY,  and add /DEFAULT or /PERMAMENT, it is equivalent to doing a SET
+SUBSCRIBE command with the addition that the specified feature  will  be
+the default and/or permanent setting. 
+3 /ALL
+Specifies that all present and future users will be  subscribed  to  the
+news group. 
+3 /DEFAULT
+   /[NO]DEFAULT
+
+Specifies that new users will automatically be subscribed  to  the  news
+group. 
+3 /PERMANENT
+   /[NO]PERMANENT
+
+Specifies that new users will automatically be subscribed  to  the  news
+group and that users cannot unsubscribe the news group. 
+2 SYSTEM
+Specifies that the selected folder is a SYSTEM folder.  A SYSTEM  folder
+is  allowed to have SYSTEM and SHUTDOWN messages added to it.  This is a
+privileged command. 
+
+  Format:
+
+    SET [NO]SYSTEM
+
+If the selected folder is remote, /SYSTEM cannot be specified unless the
+folder at the other node is also a SYSTEM folder.
+1 SHOW
+The SHOW command displays information about certain characteristics.
+2 EXCLUDE
+Displays the list of excludes which are present for the current  folder.
+The  right  hand  side  of the display shows the date of the last time a
+match for the exclude was found, and also the number of  days  from  the
+time of the last match after which the excludes expires. 
+2 FLAGS
+Shows whether BRIEF, NOTIFY, READNEW, or SHOWNEW has been  set  for  the
+currently selected folder. 
+2 FOLDER
+Shows information about a folder of messages.  Owner and description are
+shown.    If  the folder name is omitted, and a folder has been selected
+via the SELECT command, information about that folder is shown. 
+
+  Format:
+
+    SHOW FOLDER [folder-name]
+3 /FULL
+Control whether all information  of  the  folder  is  displayed.    This
+includes  DUMP  &  SYSTEM  settings,  the  access  list if the folder is
+private, and BBOARD information.  This information  is  only  those  who
+have access to that folder. 
+2 THREAD
+Displays the list of includes which are present for the current folder.
+2 KEYPAD
+Displays the keypad command definitions.
+
+  Format:
+
+    SHOW KEYPAD [key-name]  
+
+If the keypad has been enabled by either SET KEYPAD, or  if  /KEYPAD  is
+specified  on  the  command  line,  the  keypad  keys will be defined as
+commands.  The default settings for the keypad are shown via SHOW KEYPAD
+or HELP KEYPAD.  Settings can be changed by using an initialization file
+with DEFINE/KEY commands.  BULLETIN looks first for the file pointed  to
+by the logical name BULL_INIT and then for the file SYS$LOGIN:BULL.INI. 
+
+NOTE: If the keypad is not enabled, PF2 is defined to be SET KEYPAD.
+3 /PRINT
+Prints the keypad definitions on the default printer (SYS$PRINT).
+3 /STATE
+ /STATE=(state,state,...)
+
+Specifies the name of a state for which the  specified  key  definitions
+are  to  be displayed.  If you select more than one state name, separate
+them with commas and enclose the list in parentheses.  Only works when a
+key name has been specified. 
+2 LIBRARY
+Shows the library of folders.  By default there  is  only  one  library.
+However,  the system manager may decide to create more than one library,
+with each library  saved  in  a  different  directory.    Use  the  /ALL
+qualifier to see if there are other libraries. 
+3 /ALL
+Specifies to show all available libraries.
+2 NEW
+Shows folders which have new unread messages for which BRIEF or  READNEW
+have  been set.  (Note: If you enter BULLETIN but do not read new unread
+messages, you will not be notified about them the next  time  you  enter
+BULLETIN.  This is a design "feature" and cannot easily be changed.)
+2 PRIVILEGES
+Shows the privileges necessary to use privileged commands.   Also  shows
+any  rights  identifiers  that  would also give a user privileges.  (The
+latter are ACLs which are set on the BULLUSER.DAT file.)
+2 USER
+Shows the last time that a user logged in, or if /FOLDER  is  specified,
+the  latest  message which a user has read in the folder.  If NOLOGIN is
+set for  a  user,  this  information  will  be  displayed.   This  is  a
+privileged  command.   Non-privileged users will only be able to display
+the information for their own account.
+
+  Format:
+    SHOW USER [username]
+
+The username is optional.  If omitted, the process's username  is  used.
+The  username should not be included if /ALL or /[NO]LOGIN is specified.
+
+NOTE: The last logged in time displayed is that which is stored when the
+BULLETIN/LOGIN command is executed, not that  which  VMS  stores.   Some
+sites  make  BULLETIN/LOGIN  an  optional  command for users to store in
+their own LOGIN.COM, so this command can be used  to  show  which  users
+have done this.
+3 /ALL
+Specifies that information for all users is to be displayed.  This is  a
+privileged command.
+3 /LOGIN
+ /[NO]LOGIN
+
+Specifies that only those users which do not have NOLOGIN set are to be
+displayed.  If negated, only those users with NOLOGIN set are displayed.
+This is a privileged command.  The qualifier /ALL need not be specified.
+3 /FOLDER
+   /FOLDER=[foldername]
+
+Specifies to display the latest message that was read by the user(s) for
+the  specified  foldername.   A newsgroup can be specified, but the info
+can only be shown if the user has subscribed to the newsgroup.   If  the
+foldername is not specified, the selected folder will be used.
+3 /SINCE
+   /SINCE=[date]
+
+Specifies  to display only those users whose latest read message date is
+the same date  or  later  than  the  specified  date.   If  no  date  is
+specified,  the  date  of  the  current message is used.  Only valid for
+folders or with /LOGIN.  Use /START for newsgroups.
+3 /START
+   /START=[number]
+
+Specifies  to  display only those users whose latest read message number
+is equal to or greather than the specified  number.   If  no  number  is
+specified,  the  message  number  of  the current message is used.  Only
+valid for newsgroups.  Use /SINCE for folders and with /LOGIN.
+2 VERSION
+Shows  the  version  of  BULLETIN  and  the date that the executable was
+linked.
+1 SPAWN
+Creates  a  subprocess  of  the current process.  To return to BULLETIN,
+type LOGOUT.
+
+  Format:
+    SPAWN [command-string]
+
+NOTE: BULLETIN disables the use of  CONTROL-C,  so  that  you  must  use
+CONTROL-Y if you wish to break out of a spawned command.
+1 SUBSCRIBE
+Used only for NEWS folders.  Specifies that BULLETIN will keep track  of
+the  newest  message  that has been read for that NEWS folder.  When the
+NEWS folder is selected, the message pointer will automatically point to
+the next newest message that has not been read.  To see a list of the
+subscribed groups, type NEWS/SUBSCRIBE.  To automatically read news 
+groups with new messages, use INDEX/SUBSCRIBE. 
+1 THREAD
+Specifies that the current message is  defined  as  a  thread  based  on
+either  the  subject  or the message owner.  Since threads are much more
+commonly based on the subject, this is the default.  Threads are read by
+using the command READ/THREADS. 
+
+  Format:
+    THREAD [string]
+
+If a string is specified, then the message is a thread if the  owner  or
+the subject contains that string, depending on whether /FROM or /SUBJECT
+is specified.  Otherwise, if no string is specified, then the owner name
+or  subject of the current message is used.  More than one THREAD may be
+specified per folder. 
+
+Note:  EXCLUDEs take precedence over THREADs.
+2 /ALL
+Used with /DISABLE to specify to disable all THREADs.
+2 /DISABLE
+Specifies to permanently disable the THREAD.
+2 /FROM
+Specifies to include the message based on the message owner.  /FROM
+and /SUBJECT cannot be specified at the same time. 
+2 /LIMIT
+   /LIMIT=days
+
+Specifies that the thread will be automatically deleted if no match  is
+found  for the specified number of days.  The default is no limit, which
+is specified by 0.  This can be changed via the SET EXLIMIT command. 
+2 /SUBJECT
+Specifies to include the message based on the message subject.  This is
+the default.  /FROM and /SUBJECT cannot be specified at the same time.
+2 Storing_Threads
+THREADs are stored in the file SYS$LOGIN:BULL.CUSTOM or in the file
+pointed to by the logical name BULL_USER_CUSTOM.  The format is:
+
+folder_name:INCLUDE:FROM(or SUBJECT):string
+
+In order for /FULL to be the default for a folder, the following line
+must be present:
+
+folder_name:defaults:kill
+
+excluding the folder_name causes it to apply to all folders.
+1 UNDELETE
+Undeletes  he  specified  message  if  the message was deleted using the
+DELETE command.  Deleted messages are  not  actually  deleted  but  have
+their  expiration  date  set to 15 minutes in the future and are deleted
+then.  Undeleting the message will reset the expiration date back to its
+original  value.   Deleted  messages  will  be  indicated as such by the
+string (DELETED) when either reading or doing a directory listing.
+
+  Format:
+    UNDELETE [message-number]
+1 UNSUBSCRIBE
+Used only for NEWS folders.  Specifies that BULLETIN will no longer keep
+track of the newest message that has been read for that NEWS folder.  See the
+SUBSCRIBE command for further info. 
+1 Usenet_news
+BULLETIN can also read USENET NEWS if your system has network access  to
+a node which carries it.  USENET NEWS is a global bulletin board system.
+It is split into news groups.  Use the NEWS command to see the  list  of
+groups  which  are  available.  These are similar to BULLETIN's folders,
+except that the SUBSCRIBE command must be used to subscribe to  a  group
+in  order  to  keep track of which messages you have read in that group.
+Most of the other BULLETIN commands can also be used when reading NEWS. 
+
+To see a list  of  the  subscribed  groups,  type  NEWS/SUBSCRIBE.    To
+automatically  read  all  your  subscribed  news  groups  that  have new
+messages, use INDEX/SUBSCRIBE. 
diff --git a/decus/vmslt98a/bulletin/bulldir.inc b/decus/vmslt98a/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..ab5027c65ee5187fc204f90472579883ae4c1d5b
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulldir.inc
@@ -0,0 +1,58 @@
+	PARAMETER DIR_RECORD_LENGTH = (100/4)*4
+
+	COMMON /BULL_DIR/ MSG_BTIM,MSG_NUM,DESCRIP,FROM,LENGTH,EX_BTIM
+     &	,SYSTEM,BLOCK,HEADER_BTIM,HEADER_NUM,NEWEST_EXBTIM,NEWEST_MSGBTIM
+     &	,NBULL,NBLOCK,SHUTDOWN,SHUTDOWN_BTIM,NEMPTY
+     &	,DATE,TIME,EXDATE,EXTIME,NEWEST_EXDATE,NEWEST_EXTIME
+     &  ,NEWEST_DATE,NEWEST_TIME,SHUTDOWN_DATE,SHUTDOWN_TIME
+	CHARACTER*56 DESCRIP
+	CHARACTER*12 FROM
+	LOGICAL SYSTEM
+
+	CHARACTER*12 DATE,EXDATE,NEWEST_EXDATE,NEWEST_DATE,SHUTDOWN_DATE
+	CHARACTER*12 TIME,EXTIME,NEWEST_EXTIME,NEWEST_TIME,SHUTDOWN_TIME
+
+	INTEGER MSG_BTIM(2),EX_BTIM(2),HEADER_BTIM(2)
+	INTEGER NEWEST_EXBTIM(2),NEWEST_MSGBTIM(2),SHUTDOWN_BTIM(2)
+
+	CHARACTER*(DIR_RECORD_LENGTH) BULLDIR_ENTRY
+	EQUIVALENCE (MSG_BTIM,BULLDIR_ENTRY)
+
+	CHARACTER*52 BULLDIR_HEADER
+	EQUIVALENCE (HEADER_BTIM,BULLDIR_HEADER)
+
+	DATA HEADER_BTIM/0,0/,HEADER_NUM/0/
+
+	CHARACTER MSG_KEY*8
+
+	EQUIVALENCE (MSG_BTIM,MSG_KEY)
+
+	PARAMETER LINE_LENGTH=255
+	PARAMETER INPUT_LENGTH=256
+
+	COMMON /INPUT_BUFFER/ INPUT
+	CHARACTER INPUT*(INPUT_LENGTH)
+
+	PARAMETER NEWSDIR_RECORD_LENGTH = 140
+
+	COMMON /NEWS_DIR/ NEWS_MSG_NUM,NEWS_MSG_BTIM_KEY
+     &  ,NEWS_EX_BTIM_KEY,NEWS_MSGID,NEWS_POST_KEY,NEWS_BLOCK
+     &  ,NEWS_LENGTH,NEWS_DESCRIP,NEWS_FROM
+     &  ,NEWS_HEADER_KEY,NEWS_NEWEST_MSG_BTIM_KEY
+     &  ,NEWS_HEADER_FOLDER,NEWS_NEWEST_EX_BTIM_KEY,NEWS_HEADER_NUM
+     &	,NEWS_NBULL
+	CHARACTER*36 NEWS_MSGID
+	CHARACTER*56 NEWS_DESCRIP
+	CHARACTER*12 NEWS_FROM
+	CHARACTER*8 NEWS_POST_KEY
+
+	CHARACTER*8 NEWS_MSG_BTIM_KEY,NEWS_EX_BTIM_KEY
+	CHARACTER*8 NEWS_NEWEST_MSG_BTIM_KEY,NEWS_NEWEST_EX_BTIM_KEY
+	INTEGER NEWS_POST_BTIM(2)
+
+	CHARACTER*(NEWSDIR_RECORD_LENGTH) NEWSDIR_ENTRY
+	EQUIVALENCE (NEWS_MSG_NUM,NEWSDIR_ENTRY)
+
+	CHARACTER*64 NEWS_HEADER_FOLDER
+	CHARACTER*(NEWSDIR_RECORD_LENGTH) NEWSDIR_HEADER
+	EQUIVALENCE (NEWS_HEADER_KEY,NEWSDIR_HEADER)
diff --git a/decus/vmslt98a/bulletin/bullet1.com b/decus/vmslt98a/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..dff11508cd1ac1b69e08ee3e9eaff3ecddb42b2d
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullet1.com
@@ -0,0 +1,2776 @@
+$set nover
+$copy/log sys$input AAAREADME.TXT
+$deck
+The following are instructions for creating and installing the BULLETIN
+utility. None of the command procedures included here are sophisticated, so it
+is likely that several modifications will have to be made by the installer.
+The installer should enable all privileges before installation.
+
+Once installation is complete, it is suggested that the installer enter
+BULLETIN and read HELP FOLDERS to see the options available when creating
+or modifying folders.  BULLETIN creates a default folder called GENERAL
+which is a SYSTEM folder (allows messages to be posted which are displayed
+in full when people login.)  This folder can be modified (name changed,
+SYSTEM setting removed, etc.), but it will remain the default folder
+which is selected when BULLETIN is entered, and it cannot be deleted.
+
+One of the main uses of BULLETIN, besides storage of messages that are manually
+entered by users, is storage of messages from network mailing lists.  This is
+done by using the BBOARD feature, which is enabled using the SET BBOARD command
+inside BULLETIN.  The alternative method is for mail messages to be written
+directly by a mailing program by calling internal BULLETIN routines.  Such a
+a program has been written for the popular mail utilities PMDF and MX.  If you
+wish to do so for another utility, read the text file WRITEMSG.TXT.  I would be
+glad to include any such programs with my distribution if you think such a
+program would be of use to other users.
+
+Responding to mail which is added via the BBOARD feature is done using
+VMS MAIL.  The name of the mail protocol to use for responding by mail
+can be either hardcoded by putting in BULLNEWS.INC, or by defining the
+system logical name BULL_NEWS_MAILER, i.e. DEFINE BULL_NEWS_MAILER "MX%".
+
+If for some reason this is inappropriate, you can define BULL_MAILER
+to point to a command procedure, and which will be run instead of VMS MAIL.
+The parameters passed to this procedure are P1 = username and P2 = subject.
+
+1) CREATE.COM
+   This will compile and link the BULLETIN sources. Also, there are several
+   INCLUDE files for the fortran sources (.INC files). BULLETIN will create it's
+   data files in the directory pointed to by the logical name BULL_DIR.  If you
+   elect not to use this definition, BULLFILES.INC should be modified.
+   Note that after this procedure compiles the sources, it puts the objects
+   into an object library, and then deletes all the OBJ files in the directory.
+
+   CREATE.COM will automatically determine if you are running on an alpha
+   rather than a vax and will issue the appropriate commands for that cpu.
+   Of course, separate executables are needed for the two cpus, so if your 
+   site has both, you will have to run this procedure separately on each.
+
+   NOTE 1: If you plan on using the USENET NEWS reader capability of BULLETIN,
+   read NEWS.TXT for installation instructions before compiling.
+
+   NOTE 2: The maximum number of folders for this distribution is 96 folders.
+   If you wish to increase this, modify BULLUSER.INC and recompile the sources.
+   When the new executable is run, it will create a new BULLUSER.DAT data file
+   and rename the old one to BULLUSER.OLD.  You cannot reduce the number of
+   folders.
+
+2) INSTALL.COM
+   The following procedure copies the executable image to BULL_DIR and
+   installs it with certain privileges.  It also installs the necessary
+   help files in SYS$HELP.  (BULLETIN help file is installed into the
+   system help library HELPLIB.HLB.  If you don't wish this done, delete
+   or modify the appropriate line in the procedure.  Also, the help
+   library for the BULLETIN program, BULL.HLB, can be moved to a different
+   directory other than SYS$HELP.  If this is done, the system logical name
+   BULL_HELP should be defined to be the directory where the library is
+   to be found.)
+
+3) LOGIN.COM
+   This contains the commands that should be executed at login time
+   by SYS$MANAGER:SYLOGIN.COM.  It defines the BULLETIN commands.
+   It also executes the command BULLETIN/LOGIN in order to notify
+   the user of new messages.  NOTE: If you wish the utility to be a
+   different name than BULLETIN, you should modify this procedure.
+   The prompt which the utility uses is named after image executable.
+   If you want messages displayed upon logging in starting from
+   oldest to newest (rather than newest to oldest), add /REVERSE to
+   the BULLETIN/LOGIN command.  Note that users with the DISMAIL
+   flag setting in the authorization file will not be notified of
+   new messages.  See help on the SET LOGIN command within the BULLETIN
+   utility for more information on this.  Also, please note that when
+   a brand new user to the system logins, to avoid overwhelming the new
+   user with lots of messages, only PERMANENT SYSTEM messages are displayed.
+
+   If you want SYSTEM messages, i.e. messages which are displayed in full
+   when logging in, to be continually displayed for a period of time rather
+   than just once, you should add the /SYSTEM= qualifier.  This is documented
+   in BULLETIN.HLP, although there it is referred to only with respect to
+   a user wanting to review system messages.  It can be added with /LOGIN.
+
+   DECWINDOWS users should note the following: Both SYLOGIN and LOGIN are
+   executed twice, once before the terminal is actually created, while
+   SYS$OUTPUT is still a mailbox, the other time after the terminal is
+   created.  To avoid this, place the following code in both procedure. 
+   It causes them to execute only when the output is a terminal. This code
+   also helps to allow programs to be placed in LOGIN.COM that prompt for
+   terminal input.  BULLETIN does this if you select READNEW mode for
+   displaying messages when logging in, as READNEW mode will ask you if
+   you want to display the messages text.  Attempts to read terminal input
+   under DECWINDOWS when SYS$OUTPUT is still a mailbox will cause DECTERM
+   creation to fail.  (This problem is fixed under MOTIF).
+
+   $ IF F$LOCATE("_TW",F$GETJPI("","PRCNAM")) .NE. 0 THEN GOTO START
+   $ IF "''F$MODE()'" .NES. "INTERACTIVE" THEN GOTO START
+   $ IF F$GETDVI("SYS$OUTPUT","TRM") THEN GOTO START
+   $ GOTO FINISH
+   $START:
+   .
+   .
+   body of SYLOGIN.COM (including BULLETIN command)
+   .
+   .
+   $FINISH:
+   $ EXIT
+
+4) BULLSTART.COM
+   This procedure contains the commands that should be executed after
+   a system startup.  It should be executed by SYS$MANAGER:SYSTARTUP.COM.
+   It installs the BULLETIN utility with correct privileges.  It also
+   includes the command BULLETIN/STARTUP.  This starts up a detached process
+   with the name BULLCP.  It periodically checks for expire messages,cleanups
+   empty space in files, and converts BBOARD mail to messages.  It also allows
+   other DECNET nodes to share it's folders.  If you don't want this feature
+   and don't plan on having multiple folders or make use of BBOARD, you could
+   eliminate this command if you like.  However, it is highly recommended that
+   you create this process to avoid extra overhead when users login.  NOTE:
+   BULLCP normally is created so it is owned by the DECNET account.  If that
+   account does not exist, BULLCP will be owned by the account that issues
+   the BULLETIN/START command.  In that case, access via other DECNET nodes
+   will not be available.
+
+   If you are installing BULLETIN on a cluster and plan to have the bulletin
+   files be shared between all of the cluster nodes, you only need to have
+   this process running on one node. On all other nodes, the system logical
+   name BULL_BULLCP should be defined (to anything you want) so as to notify
+   BULLETIN that BULLCP is running. (On the local node where BULLCP is running,
+   this logical name is automatically defined.)
+
+   The system logical name BULL_CUSTOM can be defined to enable several 
+   features.  It is equated to a hex number string.  
+	Bit 0 set = need privileges to create folder.
+	    1 set = captive account can write files.
+	    2 set = captive account can use editor. 
+   
+   If you want to have more than one database, you can do so by redefining 
+   BULL_DIR to another directory.  However, only directories that are 
+   defined in the list of equivalence names pointed to by the system logical 
+   name BULL_DIR_LIST are allowed.  For example:
+
+	DEFINE/SYSTEM BULL_DIR_LIST SITE$ROOT:[SYSEXE],USER1:[MRL]
+
+   Then BULL_DIR can be defined as SITE$ROOT:[SYSEXE] or USER1:[MRL].  
+   BULL_DIR_LIST must be defined on all nodes in a cluster.
+   
+   The use of the MARK command to mark messages require that a file be
+   created for each user which saves the marked info.  That file file is
+   stored in the directory pointed to by the logical name BULL_MARK.  You can
+   either let users who want to use this command define it themselves, or
+   you can define it for them, i.e. DEFINE/SYSTEM BULL_MARK SYS$LOGIN.
+
+5) INSTRUCT.COM
+   This procedure adds 2 permanent messages which give a very brief
+   description about the BULLETIN utility, and how to turn off optional
+   prompting of non-system messages (via SET NOREADNEW).
+
+6) BOARD_SPECIAL.COM
+   This command procedure describes and illustrates how to use the
+   SET BBOARD/SPECIAL feature.  This feature allows the use of BBOARD
+   where the input does not come from VMS MAIL.  For example, this could
+   be used in the case where mail from a non-DEC network is not stored
+   in the VMS MAIL.  Another example is BOARD_DIGEST.COM.  This file
+   takes mail messages from "digest" type mailing lists and splits them
+   into separate BULLETIN messages for easier reading.
+
+   To use this feature, place the special command procedure into the
+   bulletin file directory using the name BOARD_SPECIAL.COM.  If you want
+   to have several different special procedure, you should name the command
+   procedure after the username specified by the SET BBOARD command.
+
+7) UPGRADE.COM
+   This procedure is used to upgrade to a new version of BULLETIN.
+   See comments for instructions.
+
+8) MASTER.COM
+   If you are using PMDF, and want to use the BBOARD option, a set of
+   routines are included which will allow PMDF to write message directly
+   into folders, which is a much more effecient way of doing it than
+   the normal BBOARD method of using VMS MAIL.  Read PMDF.TXT for how
+   to do this.
+
+9) OPTIMIZE_RMS.COM
+   This routine optimizes index files.  To run, type @OPTIMIZE_RMS.COM
+   followed by the filename.  If you omit the filename, it will prompt
+   you to allow you to turn off or on several different types of RMS
+   compression.  The default is to turn on all types of compression.
+   The optimization will cause the file to be compressed.
+
+   If you use the NEWS feature, it is suggest that you run this procedure
+   on BULLNEWS.DAT after it is created.  Compressing that file greatly speeds
+   up the NEWS update process.  If you are tight on space, and have been
+   running BULLETIN for a long time, it might also be useful to compress
+   BULLINF.DAT if that file is very large.  However, compressing that (or
+   the other BULLETIN data files) don't appear to save any execution time,
+   unlike BULLNEWS.DAT.
+$eod 
+$copy/log sys$input BULLDIR.INC
+$deck
+	PARAMETER DIR_RECORD_LENGTH = (100/4)*4
+
+	COMMON /BULL_DIR/ MSG_BTIM,MSG_NUM,DESCRIP,FROM,LENGTH,EX_BTIM
+     &	,SYSTEM,BLOCK,HEADER_BTIM,HEADER_NUM,NEWEST_EXBTIM,NEWEST_MSGBTIM
+     &	,NBULL,NBLOCK,SHUTDOWN,SHUTDOWN_BTIM,NEMPTY
+     &	,DATE,TIME,EXDATE,EXTIME,NEWEST_EXDATE,NEWEST_EXTIME
+     &  ,NEWEST_DATE,NEWEST_TIME,SHUTDOWN_DATE,SHUTDOWN_TIME
+	CHARACTER*56 DESCRIP
+	CHARACTER*12 FROM
+	LOGICAL SYSTEM
+
+	CHARACTER*12 DATE,EXDATE,NEWEST_EXDATE,NEWEST_DATE,SHUTDOWN_DATE
+	CHARACTER*12 TIME,EXTIME,NEWEST_EXTIME,NEWEST_TIME,SHUTDOWN_TIME
+
+	INTEGER MSG_BTIM(2),EX_BTIM(2),HEADER_BTIM(2)
+	INTEGER NEWEST_EXBTIM(2),NEWEST_MSGBTIM(2),SHUTDOWN_BTIM(2)
+
+	CHARACTER*(DIR_RECORD_LENGTH) BULLDIR_ENTRY
+	EQUIVALENCE (MSG_BTIM,BULLDIR_ENTRY)
+
+	CHARACTER*52 BULLDIR_HEADER
+	EQUIVALENCE (HEADER_BTIM,BULLDIR_HEADER)
+
+	DATA HEADER_BTIM/0,0/,HEADER_NUM/0/
+
+	CHARACTER MSG_KEY*8
+
+	EQUIVALENCE (MSG_BTIM,MSG_KEY)
+
+	PARAMETER LINE_LENGTH=255
+	PARAMETER INPUT_LENGTH=256
+
+	COMMON /INPUT_BUFFER/ INPUT
+	CHARACTER INPUT*(INPUT_LENGTH)
+
+	PARAMETER NEWSDIR_RECORD_LENGTH = 140
+
+	COMMON /NEWS_DIR/ NEWS_MSG_NUM,NEWS_MSG_BTIM_KEY
+     &  ,NEWS_EX_BTIM_KEY,NEWS_MSGID,NEWS_POST_KEY,NEWS_BLOCK
+     &  ,NEWS_LENGTH,NEWS_DESCRIP,NEWS_FROM
+     &  ,NEWS_HEADER_KEY,NEWS_NEWEST_MSG_BTIM_KEY
+     &  ,NEWS_HEADER_FOLDER,NEWS_NEWEST_EX_BTIM_KEY,NEWS_HEADER_NUM
+     &	,NEWS_NBULL
+	CHARACTER*36 NEWS_MSGID
+	CHARACTER*56 NEWS_DESCRIP
+	CHARACTER*12 NEWS_FROM
+	CHARACTER*8 NEWS_POST_KEY
+
+	CHARACTER*8 NEWS_MSG_BTIM_KEY,NEWS_EX_BTIM_KEY
+	CHARACTER*8 NEWS_NEWEST_MSG_BTIM_KEY,NEWS_NEWEST_EX_BTIM_KEY
+	INTEGER NEWS_POST_BTIM(2)
+
+	CHARACTER*(NEWSDIR_RECORD_LENGTH) NEWSDIR_ENTRY
+	EQUIVALENCE (NEWS_MSG_NUM,NEWSDIR_ENTRY)
+
+	CHARACTER*64 NEWS_HEADER_FOLDER
+	CHARACTER*(NEWSDIR_RECORD_LENGTH) NEWSDIR_HEADER
+	EQUIVALENCE (NEWS_HEADER_KEY,NEWSDIR_HEADER)
+$eod 
+$copy/log sys$input BULLETIN.HLP
+$deck
+1 BULLETIN
+Invokes  the  PFC  BULLETIN  Utility.  This utility is used for reading,
+adding and deleting message.  Users are notified at login time that new
+messages have been added and the topics of those messages are displayed.
+Reading of those messages is optional.  (Use  the  command  SET  READNEW
+while  in BULLETIN for setting automatic reading.)  Privileged users can
+add system bulletins that are displayed in full at  login  time.   These
+messages  are  also  saved,  and  can be read by BULLETIN.  Messages are
+automatically deleted after a specified expiration  date,  or  they  can
+manually  be  deleted  by  either  the  submitter  of  the  message or a
+privileged user.
+
+ Format:
+
+      BULLETIN [foldername or bulletin interactive command]
+
+BULLETIN has an interactive help  available  while  using  the  utility.
+Type HELP after invoking the BULLETIN command.
+
+If so configured, BULLETIN can also read USENET NEWS.
+2 Description
+
+The  BULLETIN  utility  is  a  utility to display messages to users when
+logging in.  Users are notified of  messages  only  once.   They're  not
+forced into reading them every time they log in.  Submitting and reading
+messages is easy to do via a utility similar to the  VMS  MAIL  utility.
+Privileged users can create messages which are displayed in full. (known
+as SYSTEM  messages).   Non-privileged  users  may  be  able  to  create
+non-SYSTEM  messages  (unless  your  system  manager  has  disabled  the
+feature), but only topics are displayed at login.
+
+Folders can be created so that messages pertaining to a single topic can
+be  placed  together.   Folders  can be made private so that reading and
+writing is limited to only users  or  groups  who  are  granted  access.
+Alternatively,  folders  can  be  made  semi-private in that everyone is
+allowed to read them but write access is limited.
+
+When new non-system messages are displayed, an optional feature which  a
+user  may  enable  will cause BULLETIN to ask whether the user wishes to
+read the new bulletins. The user can then read the  messages  (with  the
+ability  to  write any of the messages to a file). A user can enable the
+notification and prompting of new  messages  feature  on  a  folder  per
+folder  basis.   However,  the  exception  is  messages submitted to the
+default GENERAL folder.  Users are  always  notified  at  login  of  new
+bulletins  in  this  folder,  but can disable the prompting.  This is to
+give non-privileged users some ability to force  a  notification  of  an
+important message.
+
+Messages have expiration dates and times, and are deleted automatically.
+Expiration dates and  times  can  be  specified  in  absolute  or  delta
+notation.   Privileged  users  can  specify  "SHUTDOWN"  messages,  i.e.
+messages  that  get  deleted  after  a  system  shutdown  has  occurred.
+"PERMANENT" messages can also be created which never expire.
+
+Privileged users can broadcast their message (to either all users or all
+terminals).
+
+A user can select, on a folder per  folder  basis,  to  have  a  message
+broadcast  to  their  terminal  immediately  notifying  them  when a new
+message has been added.
+
+An optional "Bulletin Board" feature allows messages to  be  created  by
+users  of  other  systems  connected  via  networks.   A username can be
+assigned to a folder, and any mail sent to that  user  is  converted  to
+messages  and  stored  in  that  folder.   This  feature  originally was
+designed to duplicate the message board  feature  that  exists  on  some
+Arpanet  sites.  However, with the addition of folders, another possible
+use is to assign an Arpanet mailing list to a folder. For  example,  one
+could  have  an  INFOVAX folder associated with an INFOVAX username, and
+have INFO-VAX mail sent to INFOVAX.  Users could then read  the  mailing
+list  in  that  folder,  rather  than having INFO-VAX sent to each user.
+Optionally, the input for the bulletin board can be directed to be taken
+from  any  source other than VMS MAIL.  This might be useful if incoming
+mail is stored in a different place other than VMS MAIL.
+
+Messages can be either sent to a file, to a print queue,  or  mailed  to
+another user.
+
+BULLETIN  can  also  act a USENET NEWS reader if the appropriate network
+software is available to interact with.  See the installation notes  for
+more detail.
+2 Parameters
+The  parameter  following  the  BULLETIN  command  is interpreted as the
+folder name which should be selected, rather than  the  default  GENERAL
+folder.   If  the  parameter is specified with quotes ("parameter"), the
+parameter is  interpreted  as  an  interactive  BULLETIN  command,  i.e.
+commands  which are entered once BULLETIN is executed, i.e. "DIRECTORY",
+"ADD", etc.  BULLETIN will exit immediately after entering that command,
+rather than prompting for another command.  More than one command can be
+specified by separating the  commands  with  semi-colons,  i.e.  "SELECT
+DATA;DIR".  If the last command ends with a semi-colon, then BULLETIN 
+will not exit, but instead will enter the standard interactive mode and
+prompt the user for commands.
+2 /EDIT
+Specifies that all ADD or REPLACE commands within BULLETIN will select
+the editor for inputting text.
+2 /KEYPAD
+ /[NO]KEYPAD
+Specifies that keypad mode is to be set on, such that the keypad keys
+correspond to BULLETIN commands.  The default is /KEYPAD.
+2 /LIBRARY
+ /LIBRARY=library
+
+Specifies the library of folders to use.  By default there is  only  one
+library.  However, the system manager may decide to create more than one
+library, with each library saved in a different directory.  Use the SHOW
+LIBRARY/ALL command within BULLETIN to see if there are other libraries. 
+2 /PAGE
+ /[NO]PAGE
+
+Specifies  whether BULLETIN will stop outputting when it displays a full
+screen or not.  /PAGE is the default.   If  /NOPAGE  is  specified,  any
+output  will  continue  until it finishes.  This is useful if you have a
+terminal which can store several screenfuls of display in its memory.
+2 /PGFLQUOTA
+   /PGFLQUOTA=pages
+
+Used if you want to specify the page file quota for the BULLCP process.
+2 /STARTUP
+Starts up a detached process which will periodically check for expired
+messages, cleanup empty space in files, and convert BBOARD mail to
+messages.  This is recommended to avoid delays when invoking BULLETIN.
+It will create a process with the name BULLCP.  For clusters, this
+need be done only on one node.  On all other nodes, the system logical
+name BULL_BULLCP should be defined (to anything) in order that BULLETIN
+is aware that it is running on another node. (On the local node where
+BULLCP is running, this logical name is automatically defined.)
+2 /STOP
+Stops the BULLCP process without restarting a new one.  (See /STARTUP
+for information on the BULLCP process.)
+2 /SYSTEM
+   /SYSTEM=[days]
+
+Displays system messages that have been recently added.  The default is
+to show the messages that were added during the last 7 days.  This can
+be modified by specifying the number of days as the parameter.
+This command is useful for easily redisplaying system messages that
+might have been missed upon logging in (or were broadcasted but were
+erased from the screen.)
+2 /WIDTH
+   /WIDTH=page_width
+
+Specifies the terminal width for display purposes.  This is used if your
+startup procedure is configured such that BULLETIN/LOGIN is executed before
+the terminal type is known, and the default width is larger than what the
+terminal type actually is.  I.e. the default width might be 132, but the
+real width is 80.  In that case, you should add /WIDTH=80 to BULLETIN/LOGIN.
+2 /WSEXTENT
+   /WSEXTENT=pages
+
+Used if you want to specify the working set limit for the BULLCP process.
+$eod 
+$copy/log sys$input BULLETIN.LNK
+$deck
+$ ULIB = "NONE"
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .NES. "" THEN GOTO LINK
+$ IF F$TRNLNM("TWG$TCP") .EQS. "" THEN GOTO LINK
+$ ULIB = "PROCESS"
+$ DEFINE/USER LNK$LIBRARY TWG$TCP:[NETDIST.LIB]LIBNET
+$ DEFINE/USER LNK$LIBRARY_1 TWG$TCP:[NETDIST.LIB]LIBNETACC
+$ DEFINE/USER LNK$LIBRARY_2 TWG$TCP:[NETDIST.LIB]LIBNET
+$LINK:
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN GOTO ALINK
+$ LINK/NOTRACE BULL/LIB/INC=BULLETIN$MAIN,SYS$SYSTEM:SYS.STB/SEL-
+        /USERLIB='ULIB'/EXE=BULLETIN,SYS$INPUT/OPT
+SYS$SHARE:VAXCRTL/SHARE
+ID="V2.3"
+$ EXIT
+$ALINK:
+$ LINK/NOTRACE/NONATIVE_ONLY BULL/LIB/INC=BULLETIN$MAIN/SYSEXE-
+       /USERLIB='ULIB'/EXE=BULLETIN,SYS$SHARE:VAXCRTL/LIB,SYS$INPUT/OPT
+ID="V2.3"
+$eod 
+$copy/log sys$input BULLFILES.INC
+$deck
+C
+C  FOLDER_DIRECTORY IS THE DIRECTORY THAT FILES FOR FOLDERS THAT
+C  ARE CREATED ARE KEPT IN.  IF YOU WISH TO PREVENT FOLDER CREATION,
+C  YOU SHOULD MODIFY BULLCOM.CLD TO MAKE THE CREATE COMMAND A PRIVILEGED
+C  COMMAND (OR SIMPLY REMOVE THE LINES WHICH DEFINE THE CREATE COMMAND).
+C
+C  BBOARD_DIRECTORY IS THE SCRATCH AREA USED BY BBOARD WHEN EXTRACTING
+C  MAIL.  IF IT IS UNDEFINED, BBOARD WILL NOT BE ABLE TO BE USED.
+C  NOTE THAT EITHER THE BBOARD ACCOUNTS MUST HAVE ACCESS TO THIS DIRECTORY,
+C  OR THE BBOARD ACCOUNTS MUST BE GIVEN SYSPRV PRIVILEGES TO BE ABLE
+C  TO WRITE INTO THIS DIRECTORY.  ALSO, FOR BBOARD TO WORK, MAKE SURE
+C  THAT THE SUBPROCESS LIMIT FOR USERS IS AT LEAST 2.  YOU WILL ALSO HAVE
+C  TO INCREASE THE FOLLOWING SYSTEM PARAMETERS WHICH AFFECT DETACHED PROCESES:
+C  PQL_DPGFLQUOTA = 15000, PQL_DWSQUOTA = 500, & PQL_DFILLM = 30.
+C  (NOTE: ACCESS CAN BE GIVEN TO THE DIRECTORY FOR THE BBOARD ACCOUNTS USING
+C  ACLS, I.E. " SET ACL/ACL=(ID=bboard,ACCESS=R+W)/OBJ=FILE directory.DIR")
+C
+	COMMON /FILES/ BULLFOLDER_FILE,FOLDER_DIRECTORY,BBOARD_DIRECTORY
+	COMMON /FILES/ BULLUSER_FILE,BULLINF_FILE,NEWS_DIRECTORY
+	COMMON /FILES/ BULLNEWS_FILE
+	CHARACTER*80 FOLDER_DIRECTORY /'BULL_DIR:'/
+	CHARACTER*80 BBOARD_DIRECTORY /'BULL_DIR:'/
+C
+C  NOTE: THE FOLLOWING FILE ARE STORED IN THE FOLDER_DIRECTORY BY DEFAULT.
+C  YOU CAN CHANGE THIS BY ADDING A DIRECTORY NAME TO THE FILE NAME.
+C
+	CHARACTER*80 BULLUSER_FILE /'BULLUSER.DAT'/	! Stores user login time
+							! & folder flag settings
+	CHARACTER*80 BULLFOLDER_FILE /'BULLFOLDER.DAT'/	! Stores folder data
+	CHARACTER*80 BULLINF_FILE /'BULLINF.DAT'/	! Stores times of last
+							! read messages of users
+	CHARACTER*80 BULLNEWS_FILE /'BULLNEWS.DAT'/	! Stores news group data
+C
+C  THE FOLLOWING IS THE DIRECTORY THAT IS USED TO STORE LOCAL NEWS GROUPS,
+C  I.E. NEWS GROUPS THAT ARE COPIED FROM THE NEWS SERVER AND SAVED LOCALLY.
+C  BULLETIN WILL CREATE SUBDIRECTORIES IN THIS DIRECTORY AND THE FILES WILL
+C  BE STORED IN THOSE SUBDIRECTORIES.
+C
+	CHARACTER*80 NEWS_DIRECTORY /'BULL_DIR:'/
+$eod 
+$copy/log sys$input BULLFOLDER.INC
+$deck
+!
+!  The following 2 parameters can be modified if desired before compilation.
+!
+	PARAMETER BBEXPIRE_LIMIT = 30	! Maxmimum time limit in days that
+					! BBOARDS can be set to.
+	PARAMETER BBOARD_UPDATE = 15	! Number of minutes between checks
+					! for new BBOARD mail. (Note: Check
+					! only occurs via BULLETIN/LOGIN.
+					! Check is forced via BULLETIN/BBOARD).
+					! NOT APPLICABLE IF BULLCP IS RUNNING.
+	PARAMETER ADDID = .TRUE.	! Allows users who are not in the
+					! rights data base to be added
+					! according to uic number.
+
+	PARAMETER FOLDER_FMT = '(A44,A4,A8,A12,A80,A12,3A4,A8,10A4)'
+	PARAMETER FOLDER_RECORD = 220	! Must be multiple of 4
+
+	COMMON /BULL_FOLDER/ FOLDER,FOLDER_NUMBER,FOLDER_CREATED_DATE,
+     &		FOLDER_OWNER,
+     &		FOLDER_DESCRIP,FOLDER_BBOARD,FOLDER_BBEXPIRE,
+     &		USERB,GROUPB,ACCOUNTB,
+     &		F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,F_EXPIRE_LIMIT,
+     &		F_NEWEST_NOSYS_BTIM,F_START,F_COUNT,F_LAST,
+     &		FOLDER_FILE,FOLDER_SET,FOLDER_NAME
+	INTEGER F_NEWEST_BTIM(2)
+	INTEGER F_NEWEST_NOSYS_BTIM(2)
+	LOGICAL FOLDER_SET
+	DATA FOLDER_SET /.FALSE./, FOLDER/'GENERAL'/
+	CHARACTER FOLDER_OWNER*12,FOLDER*44,ACCOUNTB*8,FOLDER_NAME*80
+	CHARACTER FOLDER_FILE*80,FOLDER_DESCRIP*80,FOLDER_BBOARD*12
+	CHARACTER FOLDER_CREATED_DATE*8
+
+	CHARACTER*(FOLDER_RECORD) FOLDER_COM
+	EQUIVALENCE (FOLDER,FOLDER_COM)
+
+	COMMON /BULL_FOLDER1/ FOLDER1,FOLDER1_NUMBER,FOLDER1_CREATED_DATE,
+     &		FOLDER1_OWNER,
+     &		FOLDER1_DESCRIP,FOLDER1_BBOARD,FOLDER1_BBEXPIRE,
+     &		USERB1,GROUPB1,ACCOUNTB1,
+     &		F1_NBULL,F1_NEWEST_BTIM,FOLDER1_FLAG,F1_EXPIRE_LIMIT,
+     &		F1_NEWEST_NOSYS_BTIM,F1_START,F1_COUNT,F1_LAST,
+     &		FOLDER1_FILE,FOLDER1_SET,FOLDER1_NAME
+	CHARACTER FOLDER1_OWNER*12,FOLDER1*44,ACCOUNTB1*8,FOLDER1_NAME*80
+	CHARACTER FOLDER1_FILE*80,FOLDER1_DESCRIP*80,FOLDER1_BBOARD*12
+	CHARACTER FOLDER1_CREATED_DATE*8
+	INTEGER F1_NEWEST_BTIM(2)
+	INTEGER F1_NEWEST_NOSYS_BTIM(2)
+
+	CHARACTER*(FOLDER_RECORD) FOLDER1_COM
+	EQUIVALENCE (FOLDER1,FOLDER1_COM)
+
+	PARAMETER NEWS_FOLDER_FMT = '(A44,A4,2A8,A36,11A4)'
+	PARAMETER NEWS_FOLDER_RECORD = 144	! Must be multiple of 4
+
+	COMMON /NEWS_FOLDER/ NEWS_FOLDER,NEWS_FOLDER_NUMBER,
+     &		NEWS_F_CREATED_DATE,NEWS_F_EXPIRED_DATE,
+     &		NEWS_FOLDER_DESCRIP,NEWS_F_START,NEWS_F_COUNT,
+     &		NEWS_F_NBULL,NEWS_F_NEWEST_BTIM,NEWS_F_LAST,
+     &		NEWS_F_FLAG,NEWS_F_EXPIRE,NEWS_F_FIRST,
+     &		NEWS_F_EXPIRE_LIMIT,NEWS_F_END 
+	INTEGER NEWS_F_NEWEST_BTIM(2)
+	CHARACTER NEWS_FOLDER*44
+	CHARACTER NEWS_FOLDER_DESCRIP*36
+	CHARACTER*8 NEWS_F_CREATED_DATE,NEWS_F_EXPIRED_DATE
+
+	CHARACTER*(NEWS_FOLDER_RECORD) NEWS_FOLDER_COM
+	EQUIVALENCE (NEWS_FOLDER,NEWS_FOLDER_COM)
+
+        COMMON /NEWS_FOLDER_DEFAULT/ NEWS_FLAG_DEFAULT,
+     &	        NEWS_EXPIRE_DEFAULT,NEWS_EXPIRE_LIMIT_DEFAULT
+
+	COMMON /NEWS_FOLDER1/ NEWS_FOLDER1,NEWS_FOLDER1_NUMBER,
+     &		NEWS_F1_CREATED_DATE,NEWS_F1_EXPIRED_DATE,
+     &		NEWS_FOLDER1_DESCRIP,NEWS_F1_START,NEWS_F1_COUNT,
+     &		NEWS_F1_NBULL,NEWS_F1_NEWEST_BTIM,NEWS_F1_LAST,
+     &		NEWS_F1_FLAG,NEWS_F1_EXPIRE,NEWS_F1_FIRST,
+     &	        NEWS_F1_EXPIRE_LIMIT,NEWS_F1_END
+	INTEGER NEWS_F1_NEWEST_BTIM(2)
+	CHARACTER NEWS_FOLDER1*44
+	CHARACTER NEWS_FOLDER1_DESCRIP*36
+	CHARACTER*8 NEWS_F1_CREATED_DATE,NEWS_F1_EXPIRED_DATE
+
+	CHARACTER*(NEWS_FOLDER_RECORD) NEWS_FOLDER1_COM
+	EQUIVALENCE (NEWS_FOLDER1,NEWS_FOLDER1_COM)
+$eod 
+$copy/log sys$input BULLNEWS.INC
+$deck
+	COMMON /NEWS_DEFAULTS/ ORGANIZATION,MAILER
+
+	CHARACTER*132 ORGANIZATION
+	DATA ORGANIZATION /'MIT PLASMA FUSION CENTER'/
+
+	CHARACTER*12 MAILER
+	DATA MAILER /'IN%'/
+$eod 
+$copy/log sys$input BULLUSER.INC
+$deck
+!
+! The parameter FOLDER_MAX should be changed to increase the maximum number
+! of folders available.  Due to storage via longwords, the maximum number
+! available is always a multiple of 32.  Thus, it will probably make sense
+! to specify a multiple of 32 for FOLDER_MAX, as that it what really will be
+! the capacity.  Note that the default general folder counts as a folder also,
+! so that if you specify 64, you will be able to create 63 folders on your own.
+!
+	PARAMETER FOLDER_MAX = 96
+	PARAMETER FLONG = (FOLDER_MAX + 31)/ 32
+
+	PARAMETER USER_RECORD_LENGTH = 28 + FLONG*16
+	PARAMETER USER_FMT = '(A12,<4+FLONG*4>A4)'
+	PARAMETER USER_HEADER_KEY = '            '
+
+	COMMON /HEADER_INFO/ TEMP_USER,BBOARD_BTIM,NEWEST_BTIM,USERPRIV
+	COMMON /HEADER_INFO/ SET_FLAG_DEF,BRIEF_FLAG_DEF
+	COMMON /HEADER_INFO/ NOTIFY_FLAG_DEF
+	CHARACTER TEMP_USER*12
+	DIMENSION BBOARD_BTIM(2),NEWEST_BTIM(2),USERPRIV(FLONG)
+	DIMENSION SET_FLAG_DEF(FLONG),BRIEF_FLAG_DEF(FLONG)
+	DIMENSION NOTIFY_FLAG_DEF(FLONG)
+
+	COMMON /BULL_USER/ USERNAME,LOGIN_BTIM,READ_BTIM,
+     &		NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	CHARACTER*12 USERNAME
+	DIMENSION LOGIN_BTIM(2),READ_BTIM(2)
+	DIMENSION NEW_FLAG(FLONG)   ! Used to indicate new message in folder
+				    ! Now NEW_FLAG(2) contains SET GENERIC days
+	DIMENSION SET_FLAG(FLONG)   ! Bit set indicates READNEW set for folder
+	DIMENSION BRIEF_FLAG(FLONG) ! Bit set indicates READNEW/BRIEF set
+	DIMENSION NOTIFY_FLAG(FLONG)! Bit set indicates to broadcast
+				    ! notification when new bulletin is added.
+
+	CHARACTER*(USER_RECORD_LENGTH) USER_ENTRY,USER_HEADER
+	EQUIVALENCE (USER_ENTRY,USERNAME)
+	EQUIVALENCE (USER_HEADER,TEMP_USER)
+
+	COMMON /FOLDER_TIMES/ LAST_READ_BTIM(2,0:FOLDER_MAX)
+	   ! Must start with 0 to store info for folder specified with ::
+	COMMON /SYS_FOLDER_TIMES/ LAST_SYS_BTIM(2,FOLDER_MAX)
+	   ! Last read times for each folder as stored in BULL_DIR:BULLINF.DAT
+	COMMON /NEWS_TIMES/ LAST_NEWS_READ(2,FOLDER_MAX)
+	INTEGER*2 LAST_NEWS_READ2(4,FOLDER_MAX)
+	EQUIVALENCE (LAST_NEWS_READ2(1,1),LAST_NEWS_READ(1,1))
+	   ! Last read times for each folder as stored in BULL_DIR:BULLINF.DAT
+
+	COMMON /INF_REC/ INF_REC(2,FOLDER_MAX)
+	INTEGER*2 INF_REC2(4,FOLDER_MAX)
+	EQUIVALENCE (INF_REC2(1,1), INF_REC(1,1))
+
+	COMMON /NEW_MESSAGES/ NEW_MSG
+	DIMENSION NEW_MSG(FLONG)   ! Flag showing new messages detected
+$eod 
+$copy/log sys$input BULL_NEWS.C
+$deck
+#include <string.h>
+#include <descrip.h>
+#include <stdio.h>
+#include "sys$library:iodef.h"
+
+#if MULTINET
+
+#include "multinet_root:[multinet.include.sys]types.h"
+#include "multinet_root:[multinet.include.sys]socket.h"
+#include "multinet_root:[multinet.include.netinet]in.h"
+#include "multinet_root:[multinet.include.arpa]inet.h"
+#include "multinet_root:[multinet.include]netdb.h"
+#include "multinet_root:[multinet.include]errno.h"
+#include "multinet_root:[multinet.include.vms]inetiodef.h"
+
+static char inet[7] = "INET0:";
+$DESCRIPTOR(inet_d,inet);
+
+static struct dns {
+	unsigned char function;
+	unsigned char call_code;
+	short zeros;
+	short length;
+	char string[512];
+} buf1, buf2;
+
+struct  sockaddr_un {
+        short   sun_family;             /* AF_UNIX */
+        char    sun_path[109];          /* path name (gag) */
+};
+#else
+
+#if UCX
+
+#include <ucx$inetdef.h>
+
+struct sockaddr {
+  short inet_family;
+  short inet_port;
+  int inet_adrs;
+  char bklb[8];
+  };
+
+struct itlist { int lgth; struct sockaddr *hst; };
+
+static short sck_parm[2];
+static struct sockaddr local_host, remote_host;
+struct itlist lhst_adrs, rhst_adrs;
+
+static char ucxdev[11] = "UCX$DEVICE";
+$DESCRIPTOR(ucxdev_d,ucxdev);
+
+static int addr_buff;
+
+#define htons(x) ((unsigned short)((x<<8)|(x>>8)))
+
+#else
+
+#if TWG
+
+#include <types.h>
+#include <socket.h>
+#include <netdb.h>
+#include <in.h>
+#include <inetiodef.h>
+
+static char inet[6] = "INET:";
+$DESCRIPTOR(inet_d,inet);
+
+#else
+
+#define CMU 1
+static char ip[4] = "IP:";
+$DESCRIPTOR(ip_d,ip);
+
+#endif
+
+#endif
+
+#endif
+
+static char task[20];
+$DESCRIPTOR(task_d,task);
+
+static int s,s1;
+
+static struct iosb {
+	short status;
+	short size;
+	int info;
+} iosb;
+
+#define TCP 0
+#define DECNET 1
+
+static int mode = TCP;
+
+#if MULTINET
+
+#include <lib$routines>
+#include <stdarg.h>
+#ifdef __ALPHA
+unsigned int __VA_COUNT_BUILTIN(void);
+#define va_count(count)		(count = __VA_COUNT_BUILTIN())
+#else
+#ifdef VAXC
+#define va_count(n) vaxc$va_count(&n)
+extern int vaxc$va_count();
+#else
+#define va_count(n) decc$va_count(&n)
+extern int decc$va_count();
+#endif
+#endif
+
+static int FindRoutine(struct dsc$descriptor *image,
+		       struct dsc$descriptor *routine, int (**rtn)());
+
+int inet_ntoa1(int *arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"inet_ntoa");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = *arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int gethostname1(int arg1,int arg2)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"gethostname");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int htons1(int arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"htons");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+int gethostbyname1(int arg1)
+{
+  static $DESCRIPTOR(image,"MULTINET_SOCKET_LIBRARY");
+  static $DESCRIPTOR(routine,"gethostbyname");
+  int arglist[255];
+  int i;
+  static int status;
+  static int (*rtn)() = 0;
+  va_list ap;
+  va_count(arglist[0]);
+  va_start(ap, arg1);
+  arglist[1] = arg1;
+  for (i=1;i<arglist[0];i++)
+    arglist[i+1] = va_arg(ap, int);
+  if (!rtn)
+  {
+    status = FindRoutine((struct dsc$descriptor *)&image,
+			 (struct dsc$descriptor *)&routine,&rtn);
+    if (!(status & 1))
+      rtn = (int (*)())1;
+  }
+  if ((int)rtn != 1)
+    status = lib$callg(arglist,rtn);
+  return status;
+}
+
+static int FindRoutine(struct dsc$descriptor *image,
+		       struct dsc$descriptor *routine, int (**rtn)())
+{
+  lib$establish(lib$sig_to_ret);
+  return lib$find_image_symbol(image,routine,rtn);
+}
+#endif
+
+news_get_chan()
+{return(s);}
+
+news_set_chan(i)
+int *i;
+{s = *i;}
+
+news_disconnect()
+{
+#if UCX
+	sys$cancel(s);
+	sys$qiow(0,s,IO$_DEACCESS,0,0,0,0,0,0,0,0,0);
+#endif
+	sys$dassgn(s);
+}
+
+#if MULTINET || TWG
+
+static struct hostent *hp, *hp1;
+static struct sockaddr_in sin;
+
+#endif
+
+int *node,*node1;
+
+news_gethost()
+{
+	/*
+	 *  Get the IP address of the NEWS host.
+	 *  As of MULTINET 3.0, cannot be done at AST level
+	 *  so can't do in NEWS_ASSIGN(), as BULLCP calls it at
+	 *  AST level if the decnet gateway feature is used.
+	 */
+#if TWG
+	struct hostent *gethostbyname();
+#else
+#if MULTINET
+#endif
+#endif
+
+	node = getenv("BULL_NEWS_SERVER");
+	if (!node) return(0);
+	if (!strchr(node,'.')) return(1); 
+
+#if TWG
+	hp = gethostbyname(node);
+#else
+#if MULTINET
+	hp = gethostbyname1(node);
+#endif
+#endif
+	return(1);
+}
+
+news_assign()
+{
+	int n;
+
+	if (!strchr(node,'.')) {
+	   strcpy(&task[0],node);
+	   n = strlen(node);
+	   strcpy(&task[n],"::\"TASK=NNTP\"");
+	   task_d.dsc$w_length = 13 + n;
+	   if (!(sys$assign(&task_d,&s,0,0) & 1)) return(0);
+	   mode = DECNET;
+	   return(1);
+	}
+#if MULTINET || TWG
+	/*
+	 *  Create a "sockaddr_in" structure which describes the remote
+	 *  IP address we want to send to (from gethostbyname()).
+	 */
+
+        if (!hp) {
+          int h[4],i;
+          if (sscanf(node,"%d.%d.%d.%d",&h[0],&h[1],&h[2],&h[3]) == 4) {
+            for (i=0;i<4;i++) if (h[i] < 0 || h[i] > 255) return(0);
+	    sin.sin_addr.s_addr = (h[3]<<24)+(h[2]<<16)+(h[1]<<8)+(h[0]);
+	  } else
+	    return(0);
+	  sin.sin_family = AF_INET;
+	}
+        else {
+ 	  sin.sin_family = hp->h_addrtype;
+	  memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
+        }
+#if TWG
+	sin.sin_port = htons(119);
+#else
+	sin.sin_port = htons1(119);
+#endif
+
+	/*
+	 *  Create an IP-family socket on which to make the connection
+	 */
+
+	if (!(sys$assign(&inet_d,&s,0,0) & 1)) return(0);
+#else
+#if UCX
+         if (!(sys$assign(&ucxdev_d,&s,0,0) & 1)) return(0);
+	{
+           short retlen;
+	   struct dsc$descriptor host_name
+		= {strlen(node),DSC$K_CLASS_S,DSC$K_DTYPE_T,node};
+	   int comm = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYNAME;
+	   struct dsc$descriptor command
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&comm};
+	   struct dsc$descriptor host_ad
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&addr_buff};
+	   struct iosb nam_iosb;
+
+           if (!(sys$qiow(0,s,IO$_ACPCONTROL,&nam_iosb,0,0,
+                       &command,&host_name,&retlen,&host_ad,0,0) & 1)
+               || !(nam_iosb.status & 1)) {
+              sys$dassgn(s);
+	      return(0);
+	   }
+	}
+#else
+	if (!(sys$assign(&ip_d,&s,0,0) & 1)) return(0);
+#endif
+#endif
+	return(1);
+}
+
+struct iosb accept_iosb;
+
+nntp_listen(listen_chan)
+int *listen_chan;
+{
+#if MULTINET
+	struct sockaddr_in sin;
+	struct iosb accept_iosb;
+
+	if (!(sys$assign(&inet_d,listen_chan,0,0) & 1)) return(0);
+
+	/*
+	 *  Create an IP-family socket on which to listen for connections
+	 */
+	if (!(sys$qiow(0,*listen_chan,IO$_SOCKET,&accept_iosb,0,0,AF_INET,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	/*
+	 *  Create a "sockaddr_in" structure which describes the port we
+	 *  want to listen to. Address INADDR_ANY means we will accept
+	 *  connections to any of our local IP addresses.
+	 */
+
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = INADDR_ANY;
+	sin.sin_port = htons1(119);
+
+	/*
+	 *  Bind to that address...
+	 */
+
+	if (!(sys$qiow(0,*listen_chan,IO$_BIND,&accept_iosb,0,0,
+	   &sin,sizeof(sin),0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+ 	/*
+	 *  Declare to the kernel that we want to listen for connections
+	 *  on this port, and that the kernel may queue up to five such
+	 *  connections for us.
+	 */
+
+	if (!(sys$qiow(0,*listen_chan,IO$_LISTEN,&accept_iosb,0,0,5,
+	    0,0,0,0,0) & 1) || !(accept_iosb.status & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	return(1);
+#else
+	return(0);
+#endif
+}
+
+nntp_accept_wait(listen_chan,listen_ast,listen_iosb)
+int *listen_chan,*listen_ast,*listen_iosb;
+{
+#if MULTINET                                            
+	if (!(sys$qio(0,*listen_chan,IO$_ACCEPT_WAIT,listen_iosb,listen_ast,
+	    0,0,0,0,0,0,0) & 1)) {
+	   sys$dassgn(*listen_chan);
+	   return(0);
+	}
+
+	return(1);
+#endif
+}
+ 
+nntp_accept(listen_chan,accept_chan,accept_iosb)
+int *listen_chan,*accept_chan;
+struct iosb *accept_iosb;
+{
+#if MULTINET
+	struct sockaddr_in sin;
+	FILE *fp;
+	char buf[128];
+	char *cp, *h;
+	int s;
+	struct sockaddr_un sun = {AF_UNIX};
+
+	*accept_chan = -1;
+
+	    /*
+	     *	Call accept to accept a new connection. This 'peels'
+	     *	a connection off of the original socket and returns to us
+	     *	a new channel to the connection. We could now close
+	     *	down the original socket if we didn't want to handle
+	     *	more connections.
+	     */
+	if (!(sys$assign(&inet_d,accept_chan,0,0) & 1)) return(0);
+
+	if (!(sys$qiow(0,*accept_chan,IO$_ACCEPT,accept_iosb,0,0,
+	   &sin,sizeof(sin),*listen_chan,0,0,0) & 1)
+	   || !(accept_iosb->status & 1)) return(0);
+
+	fp = fopen("BULL_TCP_NEWS_GATEWAY", "r");
+	if (!fp) return(1);
+
+	/* A non-official way of getting ip name at ast level */
+
+	if (!(sys$assign(&inet_d,&s,0,0) & 1)) return(0);
+	if (!(sys$qiow(0,s,IO$_SOCKET,&iosb,0,0,AF_UNIX,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1))
+	    {printf("1 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	strcpy(sun.sun_path,"DNS");
+	if (!(sys$qiow(0,s,IO$_CONNECT,&iosb,0,0,&sun,sizeof(sun),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("2 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+/*	buf1.function = 1;	/* gethostbyname */
+	buf1.function = 2;	/* gethostbyaddr */
+	buf1.call_code = 0;
+	buf1.length = strlen(inet_ntoa1((int)(&sin.sin_addr)));
+ 	strcpy(buf1.string,inet_ntoa1((int)(&sin.sin_addr)));
+
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,&buf1,
+					sizeof(buf1),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("3 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	if (!(sys$qiow(0,s,IO$_READVBLK,&iosb,0,0,&buf2,
+					sizeof(buf2),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {printf("4 iosb.status = %d\n",iosb.status);sys$dassgn(s);return(0);} 
+
+	printf("5 iosb.status = %d\n",iosb.status);sys$dassgn(s);
+	buf2.string[buf2.length] = 0;
+	for (cp=buf2.string; *cp; cp++) *cp = tolower(*cp);
+
+	while (fgets(buf, sizeof(buf), fp)) {
+	    for (cp=buf; *cp != '\n'; cp++) *cp = tolower(*cp);
+	    *cp = 0;
+	    for (cp=buf; *cp == ' ' || *cp == '\t'; cp++);
+	    if (*cp == '\n' || *cp == '#') continue;
+	    if (!strcmp(buf2.string,cp)) return (1);
+	    if (*cp == '.' && strstr(buf2.string,cp)) return (1);
+	}
+	(void) fclose(fp);
+
+	return (0);
+#endif
+}
+
+news_socket()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qiow(0,s,IO$_SOCKET,&iosb,0,0,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qiow(0,s,IO$_SETMODE,&iosb,0,0,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+
+	return(1);
+}
+
+news_socket_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+	if (!(sys$qio(*efn,s,IO$_SOCKET,biosb,astadr,*astprm,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) ) return(0);
+#else
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qio(0,s,IO$_SETMODE,biosb,astadr,*astprm,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) ) return(0);
+#else
+	return(-1);
+#endif
+#endif
+
+	return(1);
+}
+
+news_create()
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qiow(0,s,IO$_CONNECT,&iosb,0,0,&sin,sizeof(sin),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+#if UCX 
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qiow(0,s,IO$_ACCESS,&iosb,0,0,0,0,&rhst_adrs,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+           sys$qiow(0,s,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s);
+	   return(0);
+	}
+#else
+	if (!(sys$qiow(0,s,IO$_CREATE,&iosb,0,0,node,119,0,1,0,300) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s);
+	   return(0);
+	}
+#endif
+#endif
+
+	return(1);
+}
+
+news_create_bullcp(efn,biosb,astadr,astprm)
+int *biosb,*astadr,*astprm,*efn;
+{
+	if (mode == DECNET) return (1);
+
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qio(*efn,s,IO$_CONNECT,biosb,astadr
+		,*astprm,&sin,sizeof(sin),0,0,0,0) & 1)) return(0);
+#else
+#if UCX
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(119);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qio(*efn,s,IO$_ACCESS,biosb,astadr,*astprm,0,
+		0,&rhst_adrs,0,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_CREATE,biosb,astadr,*astprm,node,
+		119,0,1,0,300) & 1))
+	   return(0);
+#endif
+#endif
+
+	return(1);
+}
+
+news_connect()
+{
+	if (!news_gethost()) return(0);
+	if (!news_assign()) return(0);
+	if (!news_socket()) return(0);
+	return(news_create());
+}
+
+news_write_packet(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+#if CMU
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,!mode,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#else
+	if (!(sys$qiow(0,s,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_write_packet_bullcp(efn,biosb,astadr,astprm,buf,len)
+int *biosb,*astadr,*astprm,*efn,*buf,*len;
+{
+#if CMU
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,!mode,0,0) & 1)) return(0);
+#else
+	if (!(sys$qio(*efn,s,IO$_WRITEVBLK,biosb,astadr,*astprm,buf,
+					*len,0,0,0,0) & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+news_read_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+	if (!(sys$qiow(0,s,IO$_READVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+	n = iosb.size;
+
+	return(n);
+}
+
+news_gethostname(buf)
+
+struct dsc$descriptor_s *buf;
+{
+	if (mode == DECNET) return (-1);
+#if TWG
+	return(gethostname(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+#if MULTINET
+	return(gethostname1(buf->dsc$a_pointer, buf->dsc$w_length));
+#else
+	return(-1);
+#endif
+#endif
+}
+
+
+smtp_assign()
+{
+	int n;
+
+#if MULTINET || TWG
+	/*
+	 *  Create a "sockaddr_in" structure which describes the remote
+	 *  IP address we want to send to (from gethostbyname()).
+	 */
+
+        if (!hp1) {
+          int h[4],i;
+          if (sscanf(node1,"%d.%d.%d.%d",&h[0],&h[1],&h[2],&h[3]) == 4) {
+            for (i=0;i<4;i++) if (h[i] < 0 || h[i] > 255) return(0);
+	    sin.sin_addr.s_addr = (h[3]<<24)+(h[2]<<16)+(h[1]<<8)+(h[0]);
+	  } else
+	    return(0);
+	  sin.sin_family = AF_INET;
+	}
+        else {
+ 	  sin.sin_family = hp1->h_addrtype;
+	  memcpy(&sin.sin_addr, hp1->h_addr, hp1->h_length);
+        }
+#if TWG
+	sin.sin_port = htons(25);
+#else
+	sin.sin_port = htons1(25);
+#endif
+
+	/*
+	 *  Create an IP-family socket on which to make the connection
+	 */
+
+	if (!(sys$assign(&inet_d,&s1,0,0) & 1)) return(0);
+#else
+#if UCX
+         if (!(sys$assign(&ucxdev_d,&s1,0,0) & 1)) return(0);
+	{
+           short retlen;
+	   struct dsc$descriptor host_name
+		= {strlen(node1),DSC$K_CLASS_S,DSC$K_DTYPE_T,node1};
+	   int comm = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYNAME;
+	   struct dsc$descriptor command
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&comm};
+	   struct dsc$descriptor host_ad
+		= {4,DSC$K_CLASS_S, DSC$K_DTYPE_T,&addr_buff};
+	   struct iosb nam_iosb;
+
+           if (!(sys$qiow(0,s1,IO$_ACPCONTROL,&nam_iosb,0,0,
+                       &command,&host_name,&retlen,&host_ad,0,0) & 1)
+               || !(nam_iosb.status & 1)) {
+              sys$dassgn(s);
+	      return(0);
+	   }
+	}
+#else
+	if (!(sys$assign(&ip_d,&s1,0,0) & 1)) return(0);
+#endif
+#endif
+	return(1);
+}
+
+
+smtp_create()
+{
+#if MULTINET || TWG
+
+	/*
+	 *  Do a psuedo-connect to that address. This tells the kernel that
+	 *  anything written on this socket gets sent to this destination. It
+	 *  also binds us to a local port number (random, but that is ok).
+	 */
+
+	if (!(sys$qiow(0,s1,IO$_CONNECT,&iosb,0,0,&sin,sizeof(sin),0,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#else
+#if UCX 
+        remote_host.inet_family = INET$C_AF_INET;
+        remote_host.inet_port = htons(25);
+	remote_host.inet_adrs = addr_buff;
+	rhst_adrs.lgth = sizeof remote_host;
+	rhst_adrs.hst = &remote_host;
+	if (!(sys$qiow(0,s1,IO$_ACCESS,&iosb,0,0,0,0,&rhst_adrs,0,0,0) & 1)
+	    || !(iosb.status & 1)) {
+           sys$qiow(0,s1,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#else
+	if (!(sys$qiow(0,s1,IO$_CREATE,&iosb,0,0,node1,25,0,1,0,300) & 1)
+	    || !(iosb.status & 1)) {
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#endif
+#endif
+
+	return(1);
+}
+
+smtp_disconnect()
+{
+#if UCX
+	sys$cancel(s1);
+	sys$qiow(0,s1,IO$_DEACCESS,0,0,0,0,0,0,0,0,0);
+#endif
+	sys$dassgn(s1);
+}
+
+
+smtp_connect()
+{
+	if (!smtp_gethost()) return(0);
+	if (!smtp_assign()) return(0);
+	if (!smtp_socket()) return(0);
+	return(smtp_create());
+}
+
+char node2[132];
+
+smtp_gethost()
+{
+	/*
+	 *  Get the IP address of the SMTP host.
+	 *  As of MULTINET 3.0, cannot be done at AST level
+	 *  so can't do in SMTP_ASSIGN(), as BULLCP calls it at
+	 *  AST level if the decnet gateway feature is used.
+	 */
+#if TWG
+	struct hostent *gethostbyname();
+#else
+#if MULTINET
+#endif
+#endif
+
+	node1 = getenv("BULL_SMTP_SERVER");
+	if (!node1) {
+#if TWG
+	   gethostname(node2,132);
+#else
+#if MULTINET
+	   gethostname1(node2,132);
+#endif
+#endif
+	   node1 = node2;
+	}
+
+#if TWG
+	hp1 = gethostbyname(node1);
+#else
+#if MULTINET
+	hp1 = gethostbyname1(node1);
+#endif
+#endif
+	return(1);
+}
+
+
+
+smtp_write_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+#if CMU
+	if (!(sys$qiow(0,s1,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,!mode,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#else
+	if (!(sys$qiow(0,s1,IO$_WRITEVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+#endif
+
+	return(1);
+}
+
+
+smtp_read_packet(buf)
+struct dsc$descriptor_s *buf;
+{
+	static int n,len;
+
+	len = buf->dsc$w_length;
+	if (!(sys$qiow(0,s1,IO$_READVBLK,&iosb,0,0,buf->dsc$a_pointer,
+					len,0,0,0,0) & 1)
+	    || !(iosb.status & 1)) return(0);
+	n = iosb.size;
+
+	return(n);
+}
+
+
+smtp_socket()
+{
+
+#if MULTINET || TWG
+	if (!(sys$qiow(0,s1,IO$_SOCKET,&iosb,0,0,sin.sin_family,
+	    SOCK_STREAM,0,0,0,0) & 1) || !(iosb.status & 1)) {
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#endif
+#if UCX
+	sck_parm[0] = INET$C_TCP;
+	sck_parm[1] = INET_PROTYP$C_STREAM;
+	local_host.inet_family = INET$C_AF_INET;
+	local_host.inet_port = 0;
+	local_host.inet_adrs = INET$C_INADDR_ANY;
+	lhst_adrs.lgth = sizeof local_host;
+	lhst_adrs.hst = &local_host;
+	if (!(sys$qiow(0,s1,IO$_SETMODE,&iosb,0,0,&sck_parm,0,
+	   &lhst_adrs,0,0,0) & 1) || !(iosb.status & 1)) {
+           sys$qiow(0,s1,IO$_DEACCESS|IO$M_SHUTDOWN,&iosb,0,0,0,0,0,
+						UCX$C_DSC_ALL,0,0);
+	   sys$dassgn(s1);
+	   return(0);
+	}
+#endif
+
+	return(1);
+}
+$eod 
+$copy/log sys$input CHANGES.TXT
+$deck
+Added the SET GATEWAY command to change the how the subject lines looks in
+messages which are sent to an email address associated with a folder.  2/25/98
+
+Many bugs were fixed, mainly with respect to the news-email-folder gateway.
+
+V2.3
+
+Added the ability to create a folder that can post and read to a news group,
+and can send and read messages via email.  See NEWS_TO_FOLDER.TXT for more
+info.  4/18/97
+
+Added the ability for BULLETIN to see news groups from secondary news groups
+(see NEWS.TXT).  4/18/97
+
+V 2.25
+
+Changes to make it easier to click on news group name to select them:  You can
+enter a news group name at the prompt and it will select it (without typing
+SELECT).  News groups displayed without period at end when BULLETIN lists the
+ones that have new messages.  NEWS/SUBS has space between * and news group
+when denoting which ones have new messages.  3/21/96
+
+V 2.24
+
+When replying to a message in a news group that has been crossposted, give the
+user  the  option  of  just  posting  the reply to the news group in which the
+message is being read rather than  all  the  news  groups  in  the  crosspost.
+11/20/95
+
+Messages added to folders and stored news groups are now marked as being  read
+so that the person does not see them when doing a READ/NEW.  11/20/95
+
+Removed INCLUDE command and replaced it with the THREAD command.    This
+allows  you  to  save  and  easily  read new messages in threads via the
+READ/THREADS command.  11/13/95
+
+V 2.23
+
+Update newest read message when switching folders.  Previously this was done
+only when you exited BULLETIN, which would cause problems if you ran BULLETIN
+simultaneously from two different logins.  9/12/95
+
+Added /LIMIT to EXCLUDE and also the SET EXLIMIT command.   These  allow
+excludes to be specified so that they expire after a specified amount of
+days.  The SHOW EXCLUDE now will show the last time a message was found 
+that matched the exclude.  8/16/95
+
+Added /GROUP qualifier to DIRECTORY command to allow  specifying  groups
+to search using wild cards names.  8/3/95
+
+Added /GROUP qualifier to SEARCH command to allow specifying  groups  to
+search using wild cards names.  6/20/95
+
+V 2.22
+
+Added SHOW EXCLUDE and INCLUDE commands.  5/17/95
+
+Fixed bugs relating to messages with an expiration year past 1999.  5/17/95
+
+Fixed EXCLUDE/FROM as it did not work.   Also  fixed  EXCLUDE/DISABLE/ALL  and
+INCLUDE/DISABLE/ALL, as in some cases they would not work.3/31/95 
+
+V 2.21
+
+Modified the file format for stored news group to reduce disk space usage.
+11/29/94
+
+Added SET LIBRARY command and also /LIBRARY qualifier on the command line to
+allow switching between different directories which contain different sets of
+folders.  11/29/94
+
+Added /HEADER to POST when posting to news groups to allow adding headers to
+the message.  11/9/94
+
+Added /CANCEL to PRINT command which cancels previous print commands.
+10/28/94
+
+V 2.20
+
+Added /FOLLOWUP to the POST command.  10/12/94
+
+The FILE command no longer requires a file name, but will create a file
+name from the folder's name.  5/25/94
+
+Allow logical names to be specified in POST/GROUP.  5/12/94
+
+Added SET FILE_DIRECTORY command.  5/12/94
+
+Added /PERMANENT and /DEFAULT qualifiers to NEWS command.  4/28/94
+
+Added SET SUBSCRIBE command to allow setting default or permanent news groups. 
+4/26/94
+
+Added code to mail rejected posting for a stored news group to poster.  4/6/94
+
+Optimized newsgroup list upgrade to reduce  disk  I/O  which  greatly  reduces
+elapsed time for slow or fragmented disks.  4/5/94
+
+Modified /EDIT so EDT error no longer shows "no file found" message.  4/5/94
+
+Added SET NAME command to copy settings, used if username is changed.  3/28/94
+
+Modified SEARCH command to avoid updating new message counter (in order to be
+able to follow a thread and still use READ/NEW later).  3/26/94
+
+Added /INDENT=string to allow different indentation string.  3/12/94
+
+Added ability to allow BULLCP to gateway for NEWS access via TCP (for MULTINET
+only).  2/24/94
+
+Fix FROM header for news groups messages that have an address which continues
+on a 2nd line.  12/17/93
+
+V 2.19
+
+Add /MATCH qualifier to SEARCH command, and allow more than 1 string to be
+specified.  12/2/93
+
+Fixed the qualifer /CC when posting or resonding to messages.  It was supposed
+to be able to send to more than one user, but actually was sending to only the
+first user specified.  7/17/93
+
+Fixed alpha related problems.  7/16/93
+
+Fixed problem with responding to addresses of form: name <address>.  7/2/93
+
+Fixed shutdown bugs.  6/6/93
+
+Fixed /PRINT and /EXTRACT in DIRECTORY when used with a remote news group.
+5/29/93
+
+System messages which have longer lines than the terminal page width will have
+their text left justified rather than simply wrapped.  5/28/93
+
+Added SET [NO]EXCLUDE command to be  able  to  ignore  any  excludes  or
+includes that have been specified for that folder.  5/20/93
+
+V 2.18
+
+Added /FULL to EXCLUDE  and  INCLUDE  command  to  make  it  affect  all
+commands, such as directory listings.  5/13/93
+
+Fixed bug which displayed wrong foldername for notification broadcasts for
+messages added to bboard folders with digest set.  5/13/93
+
+Fixed bug which caused FOR003.DAT files to appear in DECNET directory due to
+BBOARD folder which has digest set.  5/10/93
+
+Fixed problem with inserting correct time when posting to news group.  5/5/93
+
+Fixed problem with BULL_DIR_LIST usage.  5/5/93
+
+Fixed shutdown problems.  5/3/93
+
+Fixed new executable message.  5/3/93
+
+Fixed bugs which caused FOR00x.DAT files to appear in DECNET directory during
+access from remote nodes.  4/29/93
+
+V 2.17
+
+Modified to work for ALPHA cpus.  4/5/93
+
+Speeded up DIRECTORY listing.  3/18/93
+
+Fixed FORWARD command from truncating subject lengths > 64.  3/18/93
+
+V 2.16
+
+Add code which causes nodename of remote folders to automatically be updated
+when the bulletin data files of the node containing the remote folders are
+moved to a different node.  3/12/93
+
+Fix incorrect display of NEWS/SUBSCRIBE/COUNT.  3/6/93
+
+In batch mode, paging is now automatically turned off and page width set to 80.
+3/5/93
+
+Fixed problem with shutdown messages not being deleted.  3/4/93
+
+V 2.15
+
+Code that converts data files if FOLDER_MAX is increased did not work.  2/27/93
+
+NEWS/SUBS now shows last read message.  INDEX now shows listing similar to
+DIR/FOLDER and NEWS. 2/27/93
+
+A user can make /HEADER be made the default for a folder or news group by adding
+a line to the user's customization file.  (See HELP custom) 2/21/93
+
+Personal names which are set in VMS MAIL are now automatically added to the from
+address when posting to news groups.  2/15/93
+
+Fixed bug which caused only partial storage of specified local news groups.
+2/5/93
+
+Fixed bug that caused privilege error and crash to occur after a non-privileged
+user posted a message to a folder which had an associated mailing list.  2/5/93
+
+V 2.14
+
+Added SET ANONYMOUS command so that all messages added to a folder will have
+the username ANONYMOUS rather than the actual username.  2/1/93
+
+Added /EXTRACT qualifie to DIRECTORY command.  1/31/93
+
+Added notification of new executable and possible new features.  1/26/93
+
+Dump log files are now created with acl for folder owner to be able to delete
+it.  1/26/93
+
+V 2.13
+
+Fixed bug in BBOARD code that corrupts file length.  1/15/93
+
+Fixed notification messages that showed wrong folder name.  1/15/93
+
+Added /[NO]HEADER and /ROTATE to NEXT (help said they were there, but they
+weren't).  1/15/93
+
+Added RESET command.  1/9/93
+
+Fixed bug in posting to stored news group by non-privileged users.  12/28/92
+
+V 2.12
+
+Fixed SET ACCESS /ALL which broke due to changes in V 2.11.  12/28/92
+
+Fixed problem with reply posting to stored news group not posting to proper
+group.  12/28/92
+
+Added code to allow setting access to news group or class of news groups.
+Added /PRIVATE switch to SET NEWS.  Added /CLASS to SET ACCESS.  12/26/92
+
+Fixed bug in code that does copying from news group to folder.  12/26/92
+
+Added INCLUDE and EXCLUDE commands which allow avoiding reading messages based
+on subject and address headers.  12/15/92
+
+Fixed bug which caused folder corruption.  12/15/92
+
+V 2.11
+
+Added SET NEWS command.  Used for setting a news group or a class of news
+groups to be stored on disk for quicker access by users (rather than being 
+read by users directly from the server).  Can also disable access to a group. 
+Users can set NOTIFY on stored groups.  11/5/92
+                                       
+NEWS command now by default shows only groups which are active.  Can show all
+groups with /ALL command.  /STORED and /COUNT are new qualifiers.  11/5/92
+
+Stored news groups are stored with data compression.  Normal folders can also be
+stored that way if set with the SET COMPRESS command.  11/5/92
+
+INDEX command modified to make it more useful.  /NEW is now the default, and now
+only shows folders or groups that have new messages.  /SET added to show only
+folders which have READNEW, SHOWNEW, or BRIEF set, and /SET is the default.
+11/5/92
+
+Fixed bug with BROADCAST routines which could cause BULLCP to go into MWAST
+state.  11/5/92
+
+Modified code which adds BBOARD messages to speed it up when multiple messages
+are being added.  11/5/92
+                                                 
+Folder names can now be up to 44 letters long.  11/5/92
+
+BULL_BBOARD_UPDATE and BULL_NEWS_UPDATE are now continuously translated by
+BULLCP so that they can be changed dynamically.  11/5/92
+
+BULLCP now is created with reasonable working quotas rather than PQL_ defaults
+which are usually way too low.  11/5/92
+
+Changed all variables to be long word multiples in order to be more ALPHA
+compliant (and maybe faster because of it?).  11/5/92
+
+/ROTATE added for read commands to allow reading messages encoded in ROT-13
+coding.  This is used by some news groups to display messages which could be
+taken as being offensive (i.e. rec.humor.funny).  11/5/92
+
+Fixed many minor bugs that no one mentioned, so I won't either.  11/5/92
+
+Fixed ADD/BROADCAST/EDIT not working with TPU.  8/13/92
+
+V 2.10
+
+Allow non-digest messages to be added to a folder which has DIGEST set.  8/6/92
+
+Added ADD_ONLY attribute.  If a mailing address is present, when messages are
+added to a folder, they will also be mailed to the address.  Users are
+prevented from using the POST command.  Instead, the ADD command will be used
+if the POST command is entered.  One use for this is a local board which is
+also distributed to non-local users.  8/1/92
+
+Added POST_ONLY attribute  This causes the ADD command to mail messages to the
+mailing address if it is present, rather than add it to the folder.  8/1/92
+
+Fixed several shutdown bugs.  7/23/92
+
+Fixed PMDF broken by V2.09.  6/16/92
+
+Added system logical name BULL_CUSTOM.  It is equated to a hex number string.  
+Bit 0 set = need privileges to create folder, 1 set = captive account can
+write files, 2 set = captive account can use editor.  5/25/92
+
+V 2.09
+
+Allow having more than one database by redefining BULL_DIR.  However, only 
+directories that are defined in the list of equivalence names pointed to by
+the system logical name BULL_DIR_LIST are allowed.  See AAREADME.TXT
+for more info.  5/10/92
+
+GENERAL folder can now be renamed or modified (not deleted).  4/22/92
+
+/FROM, /NOREPLIES, & /NEGATED added to SEARCH and DIRECTORY commands.  3/18/92
+
+Mail routines now use MAIL$ calls for outgoing mail for faster execution.  
+3/15/92
+
+Changing keypad definitions using initialization file now possible.  3/12/92
+
+Subscribed news groups are now listed in alphabetical order.  3/7/92
+
+V 2.08
+
+Fixed bug which caused missing news groups. See NEWS.TXT for info.  2/25/92
+
+Allow setting local protection on remote folders.  12/12/91
+
+Fixed bug with creation of folder files.  If they were deleted after the folder
+was created, the files that would be created by BULLETIN to replace them (when
+the folder is selected) would be created with the wrong protection.  12/12/91
+
+Fix problem with MULTINET V3.0 and DECNET/NEWS gateway feature.  BULLCP will
+hang without this fix if there is an attempt to read news via it.  12/9/91
+
+Fix bug that causes incorrect time on news postings after the first post. 
+Display time when reading news messages in local rather than GMT time.  12/8/91
+
+Add 30 second timeout for connecting to nameserver for news.  Can be increased
+up to 99 seconds via defining BULL_NEWS_TIMER.  12/3/91
+
+Allow list of numbers when specifying message numbers for PRINT and FILE
+commands.  11/27/91
+
+Fixed bugs in BBOARD code:  Messages with lines > 255 characters would not be
+included.  Subject line not correctly extracted if next line was simply a
+To:. (relink PMDF driver if using PMDF for patch to take affect).  11/27/91
+
+V 2.07
+
+NEWS listing now shows the status of the news group, i.e. active, inactive,
+moderated, or renamed.  10/23/91
+
+Fixed PRINT command so that if a print qualifier (i.e. /QUEUE) is specified,
+it will cause any pending print jobs to be printed if the qualifier for the
+pending jobs is different.  10/23/91
+
+Added /NOSIGNATURE qualifier for POST & RESPOND commands.  10/21/91
+
+Fixed error in POST & RESPOND command.  If a file was specified on the command
+line, and /EDIT was specified, the file would be sent even if the user quit out
+of the edit, rather than exitting (i.e. outputting a file).  10/21/91
+
+Fixed REPLY option in READNEW, as it was possible for users with only read
+access to a folder to be able to add REPLY messages.  10/10/91
+
+Add REPLY option to READNEW feature when reading messages.  Also, really fix
+the REPLY command, as mentioned in V2.06.  8/11/91
+
+V 2.06
+
+Added code to keep track of which messages have been read a per message basis. 
+Added SEEN & UNSEEN commands.  Added /SEEN, /UNSEEN, and /UNMARKED to
+DIRECTORY, INDEX, READ, and SELECT commands.  Modified directory listing to
+indicate which messages have been SEEN.  7/31/91 
+
+Added /NOW to PRINT command.  Messages no longer have to be printed one message
+at a time.  It now works identical to VMS MAIL.  7/31/91
+
+Added code to NEWS users when new groups have been created.  User will be
+alerted when selecting a news group that new groups are present, and will be
+instructed to type NEWS/NEWGROUP in order to see them.  7/31/91
+
+Added /PRINT to DIRECTORY command to allow printing of messages which are found
+by using the DIRECTORY command.  7/31/91
+
+Modified directory listing display so that the first and last message in the
+folder are now displayed at the top.  Fixed bug which truncated very large news
+group names.  7/31/91
+
+Added FIRST command to read first message found in folder.  7/31/91
+
+Modified REPLY command for folders associated with mailing lists, so that the
+reply message to the mailing list rather than adding a local message.  7/31/91
+
+Modified code to correctly store subject headers from BBOARD mail which are
+more than one line long.  Previously, the subject would be truncated.  6/18/91
+
+V 2.05
+
+The MARK code was modified to work with NEWS folders.  6/3/91
+
+Added /FOLDER=(folder,[...]) to the SEARCH command to allow searching more than
+one folder at a time.  6/13/91
+
+NEWS/SUBSCRIBED listing was fixed.  If the list could not fit on a single page,
+a folder was skipped when the next page was shown.  6/3/91
+
+INDEX was fixed.  If it was used with the qualifiers /NEW or /MARK, and the
+directory listing of a folder was displayed, and then RETURN is entered to 
+skip to the next folder, the directory display of the next folder would be
+incorrect.  6/3/91 
+
+Fixed broadcast bug.  If a message was added with /BROADCAST to a remote folder
+from a node in a cluster which was not the node that BULLCP was running on. 
+The broadcast would appear twice on the cluster.  5/24/91
+
+Added code to alert user if message too large to be fully broadcasted.  5/24/91
+
+Added code to avoid erroneous notifications of new messages for an empty NEWS
+group.  Unlike a similar fix in V2.03 which was due to a bug, this fix may not
+affect all sites, as it depends on the behavior of the server.  5/22/91 
+
+Fixed NEWS to FOLDER feed.  A recent change broke it.  5/22/91
+
+Added /EDIT qualifier for MAIL.  5/20/91
+
+Added /HEADER qualifier for LAST, BACK, and CURRENT commands.  5/19/91
+
+Added TWG (Wollongong) interface for NEWS.  5/18/91
+
+Fixed bug which truncated subject headers of messages created when using REPLY
+and RESPOND to messages which have long subject lines.  5/12/91
+
+V2.04
+
+Added ALWAYS attribute for folders.  Any SYSTEM messages in a folder in which
+ALWAYS has been set will be displayed every time a user logs in, rather than
+just once.  Also, non-SYSTEM messages will be displayed continuously (via
+whatever mode is set, i.e. READNEW, SHOWNEW, or BRIEF) until it is actually
+read.  4/29/91 
+
+Added capability of controlling the time between updates for BBOARD and NEWS in
+BULLCP by defining the logical names BULL_BBOARD_UPDATE or BULL_NEWS_UPDATE to
+the number of minutes of desired time in minutes. 4/27/91
+
+Added /GROUPS= qualifier to all commands which post to NEWS groups. 4/26/91
+
+Fixed bug which prevented SET SHOWNEW or READNEW from working with subscribed
+news group folders. 4/25/91
+
+V2.03
+
+Added /FOLDER to SHOW USER in order to show the latest message that a user
+has read in the specified folder.  Also added /SINCE and /START (the former
+for real folders, the latter for news groups).  4/11/91
+
+Fixed logic so that defining BULL_NEWS_ORGANIZATION will override the
+definition defined in BULLNEWS.INC.  4/10/91
+
+Fixed SEARCH command, as it broke in V2.02 when /EDIT was added to read
+message commands.  There is a missing QUALIFIER EDIT in BULLCOM.CLD for the
+SEARCH verb.  /EDIT now works with SEARCH.  4/9/91
+
+Fixed bug in BULLCP which prevented the DECNET/INTERNET NEWS gateway software
+from working with UCX.  4/9/91 
+
+Fixed bug caused by V2.00 which caused incorrect listing of message during
+BULL/LOGIN for remote folders.  4/3/91
+
+Fixed bugs which caused erroneous new message notifications for subscribed
+NEWS groups that were empty.	3/27/91
+
+V 2.02
+
+Include BBOARD support for MX (courtesy of goathunter@wkuvx1.bitnet).
+
+Changed BBOARD algorithm so that it is now possible to have only one real
+BBOARD account, and have all the others be VMS MAIL forwarding entries.
+See HELP SET BBOARD MORE_INFO for more info (it's been updated).
+
+Added hook to allow postings from BULLETIN to a LISTSERV mailing list to use
+the BBOARD account from it was subscribed to.  See HELP SET BBOARD LISTSERV.
+
+Fixed many bugs in POST, REPLY, and RESPOND.
+
+Fixed /ALL for COPY, PRINT, and EXTRACT when using NEWS groups.
+
+Included RMS optimizer procedure for indexed files to optimize BULLNEWS.DAT
+to speed up NEWS updates.  Can be used on other files (in particular
+BULLINF.DAT) in order to save space.
+
+Add /EDIT to BACK, NEXT, LAST, and when entering message number.
+
+Modify ADD/REPLY command to local (non-NEWS) folders so if there are new
+messages present, it doesn't reset the newest message count.  Previously,
+adding a message would reset the user's last read message date to that message
+in order to avoid notifying the user of new messages due to the user's own
+message. 
+
+Fixed code so that when reading new messages, and if READ/EDIT or DELETE/IMMED-
+IATE IS entered, a carriage return will read the next new message.  Previously
+the wrong message would be displayed.
+
+V 2.01
+
+Fixed many bugs associated with USENET NEWS reading feature.
+
+Added UCX interface for NEWS.
+
+Added signature file for POST and RESPOND messages.
+
+Added capability to specify file name for POST, REPLY, and RESPOND.
+
+Added the line "In a previous message, <message-owner> wrote:" to the
+beginning of a message when /EXTRACT is specified
+
+Added hook for network mail to run command procedure rather then using
+VMS MAIL.  BULL_MAILER can be defined to point to the procedure, and it
+is called with the username and subject as the parameters.
+
+V 2.00
+
+Added USENET NEWS reading feature.
+
+V 1.93
+
+Fixed bug which wouldn't allow a permanent message to be added by a
+non-privileged user in a remote folder (the folder had been setup to allow
+permanent messages from non-privileged users, of course). 
+
+Fixed bug which causes the DELETE command not to delete a SHUTDOWN message
+without the use of /IMMEDIATE.
+
+Fixed the algorithm which prevented duplicate notification of messages in
+remote folders on different nodes, as duplication was still possible.
+
+V 1.92
+
+Fixed bug which causes BULLCP to loop when trying to cleanup a folder which
+has more than 127 identifiers granted access to a folder.  Also correct
+SHOW FOLDER/FULL, which had a similar problem when trying to display the
+identifiers.
+
+Fix PMDF interface to recognize to recognize PMDF_PROTOCOL.
+
+V 1.91
+
+Disallow SPAWN command for CAPTIVE account.
+
+Fix MAIL command to correctly allow passing addresses with quotes, i.e.
+IN%"""MRL@NERUS.PFC.MIT.EDU""".
+
+V 1.90
+
+SET NOTIFY now works for remote folders.
+
+Avoid generating notification message due to SET NOTIFY flag if the message
+was broadcasted when added using ADD/BROADCAST.
+
+Bug in DIR/SINCE for remote folders fixed.  If no new messages were present,
+it would incorrectly show messages.
+
+Added /FF to EXTRACT command to seperate messages in the file with form feeds.
+
+Allow specifying CURRENT and LAST when specifying a range of messages for
+commands that accept a range, i.e. EXTRACT 1-CURRENT, CURRENT-LAST, etc.
+
+Open folder files with READONLY when not writing to them in order to avoid
+changing modification date, which results in unnecessary backups.
+
+Modify HELP so that it won't prompt for Subtopic is there is none.
+
+Prevent screen from being erased after exiting HELP.
+
+Fix bug which causes CREATE/NOTIFY to crash.
+
+SET NOTIFY/CLUSTER has been removed.  As of VMS V5.2, it is possible to obtain
+the list of users logged in to all nodes of a cluster, so this qualifier is no
+long necessary.  NOTE: You can delete all the BULL_DIR:*.NOTIFY files, as they
+are no longer used.
+
+BULLETIN now will use the editor specified by the SET EDITOR command within
+MAIL for editing messages.
+
+Typing BACK after typing a DIRECTORY command will now show the previous 
+DIRECTORY display entries rather than reading the previous message.
+
+Several bugs related to the MARK command were fixed.  Also the software has been
+optimized so that scanning for MARKed messages should take less time.
+
+/EXPIRATION added to DIRECTORY command to show expiration rather than creation
+date of messages.
+
+Any BULLETIN interactive command can be executed at DCL level by typing
+BULLETIN "command" or BULLETIN "command1;command2;etc.".
+
+The CHANGE command has been modified so a range of message can be specified,
+i.e. /NUMBER=1-10.  Also, the code incorrectly misinterpreted /TEXT as meaning
+to extract the old text message, whereas it should have meant that only the
+text was to be changed.  This prevented a user from specifying that only the
+text should be changed if that user didn't have editing enabled.  This has been
+fixed.  To eliminate confusing, the /TEXT qualifier on the ADD command has been
+removed (previously it was a synonym for /EXTRACT). 
+
+SHOW FOLDER/FULL display of access IDs was fixed to correctly display UICs.
+
+Removed security hole which occurs if you are using the old method of accessing
+a remote node via /NODES (it would have required looking a the sources to find,
+which one installer did and was worried about).  Because of this, if you use
+this old method (i.e. via BULLETIN.COM), the object BULLETIN must be installed
+in the NCP database pointing to the file BULLETIN.COM, i.e. the command
+"MCR NCP SET BULLETIN FILE directory:BULLETIN.COM NUMBER 0" must be executed
+during the system startup.
+
+Fixed bug in /LOGIN display when erasing page if terminal is hardcopy.  No
+page would be erased (of course), and the next line outputted would start where
+the previous line left off, rather than starting on a new line.
+
+Added BULLETIN/WIDTH=page_width for users who have BULLETIN/LOGIN in their
+login procedure before the terminal is known, and whose default page width is
+larger (i.e. 132) than what the terminals are (i.e. 80).
+
+Added BULLETIN/PGFLQUOTA and /WSEXTENT in order to set those quotas for the
+BULLCP process.
+
+Added ATTACH command.
+
+Modify SET STRIP so that it saves the date that the message was sent and
+leaves it at the to of the message.
+
+BULLETIN will search BBOARD message headers for a line that starts with
+"Expires:" or "X-Expires:", followed by a date (DD MMM YYYY or similar).  It if
+finds that line, it will use that date as the expiration date of the message. 
+
+Added /REPLY to SEARCH command.  Modified so that it's possible to abort out of
+a /SUBJECT or /REPLY search using CTRL-C (previous possible only if searching
+the text for a string.  Also, if you hit CTRL-C at the wrong time, BULLETIN
+would abort totally rather than just aborting the search). 
+
+Added /SEARCH= /SUBJ= and /REPLY to the DIRECTORY command.  Basically this is
+combining the DIRECTORY and SEARCH commands.
+
+Fixed design flaw which allowed the following to occur:  If a folder is a
+remote system folder, when BULLETIN/LOGIN was executed, the same messages might
+be displayed on both the local and remote nodes.  BULLETIN now will know that
+the user has seen the message on one node and will not display it if that user
+logs in on the other node.
+
+Optimized code which caused slow display of new messages when executing
+BULLETIN/LOGIN without /REVERSE for a remote folder.
+
+Added /PERMANENT to SET NOTIFY, SHOWNEW, BRIEF, and READNEW.  The affect is
+that users will not be allowed to change the setting.  The main intent here
+was to allow the removal ofthe permanent setting of SHOWNEW from the GENERAL
+folder.
+
+Fixed bug which would cause a SYSTEM message not to be shown if SET BRIEF was
+selected for that folder, and a non-SYSTEM message was also present.
+
+Added SET CONTINUOUS_BRIEF.  This causes the SET BRIEF setting to show that
+there are unread new messages every time BULLETIN/LOGIN is executed, rather
+than just the one time.  The BRIEF notification code has also been optimized
+so that it'll take less time to notify you of new messages.
+
+A major bug was fixed which was introduced in previous mods to speed up
+BULLETIN/LOGIN.  The effect is that no notifications will appear for certain
+folders via BULLETIN/LOGIN.  This would only happen if a folder was removed at
+some time.
+$eod 
+$copy/log sys$input DEBUG.TXT
+$deck
+$eod 
+$copy/log sys$input HANDOUT.TXT
+$deck
+               Introduction to BULLETIN on the Vax
+                                                  2/88 AW
+
+PUBLISHED BY THE DREW UNIVERSITY ACADEMIC COMPUTER CENTER. MAY BE
+COPIED WITH WRITING CREDIT GIVEN TO DREW UNIVERSITY.
+
+BULLETIN was written for the Public Domain by Mark London at MIT.
+
+     The BULLETIN utility permits a user to create messages for
+reading by other users.  Users may be notified upon logging on
+that new messages have been added, and what the topic of the
+messages are.  Actual reading of the messages is optional.  (See
+the command SET READNEW for info on automatic reading.)  Messages
+are automatically deleted when their expiration data has passed.
+     The program runs like VAX mail.  The different interest
+groups or BULLETIN boards are implemented in the form of
+'Folders', just like a filing cabinet.  A Folder contain various
+messages on the same general topic.  A message is a piece of text
+written by a user or staff person and added to a particular
+folder.  All users are not permitted to submit messages to all
+folders.
+
+     A message consists of an expiration date, a subject line
+and the text of the message.  BULLETIN will prompt the user for
+these things when a message is being added.
+
+     Several different folders are currently defined to
+BULLETIN.  The General Folders will be used by Computer Center
+Staff to post messages of general interest concerning the VAX to
+the user community.  If something is of an important nature, it
+will be posted in the General folder as a 'System' message.
+This is a special message type.  It will be displayed to each
+user  as they log in the first time after that message was
+posted.  This will be done automatically by BULLETIN on login.
+Once a particular system message has been displayed, it will not
+be displayed for that user on subsequent logins.
+
+Folders
+
+     Different folders have been created to contain messages on
+different topics.  Folders may be public, semi-private, or
+private.  The majority of the folders will be public.  However a
+few will be semi-private, which will mean that all users may
+read messages in the folder but not all will be able to post to
+it.  Currently, there are several folders defined:
+
+GENERAL -- system messages
+
+PUBLIC_ANNOUNCEMENTS -- Can be used by anyone to post messages
+of interest to the public
+
+On Beta:
+AIDE STATION -- Private folder for Computer Center Employees
+
+In addition on Alpha there are folders that receive electronic
+magazines, such as:
+NETMONTH --  The monthly magazine of BITNET information.
+RISKS -- Identifying the risks involved in using computers.
+INFOIBMPC -- Information about the IBM personal computers.
+INFOVAX -- Information on the Digital VAX.
+PROGRAMMING_JOURNALS-Includes MINIX, UNIX and C, Modula-2 and
+Prolog journals
+watch for new ones being added.
+
+Using BULLETIN
+
+     BULLETIN is invoked by type the command 'BULLETIN' (or BULL,
+for short) at the '$' prompt.  BULLETIN will display its prompt
+'BULLETIN>'. Help is available from DCL command level ($) or from
+within the BULLETIN program itself by typing the word 'HELP'.  To
+leave the BULLETIN program, type 'EXIT'.
+
+To see what is there
+
+     In order to see message and folders, on can use the
+'Directory' command. Upon entering BULLETIN, the user is place
+in the General folder.  If the user wishes to see which folders
+exist, the directory/folders command is used. for example:
+typing:
+
+     BULLETIN> directory/folders
+
+will make a display like:
+
+      Folder                       Owner
+     *GENERAL                      SYSTEM
+     *PUBLIC_ANNOUNCEMENTS         BBEYER
+      NETMONTH                     BITNET
+     *VAX_SIG                      BBEYER
+
+An asterisk (*) next to the folder name indicates you have unread
+messages in that folder.
+
+The command 'DIRECTORY/FOLDERS/DESCRIBE' would list all available
+folders, along with a brief description of each.
+
+     To switch from one folder to another folder, the user may
+execute the 'SELECT' command.  For example, the following
+command would show what a user would do to switch to the folder
+called PUBLIC_ANNOUNCEMENTS:
+
+BULLETIN> SELECT PUBLIC_ANNOUNCEMENTS
+
+and BULLETIN would respond:
+     Folder has been set to PUBLIC_ANNOUNCEMENTS
+
+     Now the user may get a list of the messages in this folder
+by issuing the directory command with no qualifiers.
+This command, for example:
+BULLETIN> DIRECTORY
+would have bulletin respond:
+
+ #     Description               From                  Date
+ 1     CHRISTMAS PARTY           oleksiak              26-JUN-88
+ 2     Learning about BULLETIN   oleksiak              26-JUN-87
+ 3     VAX MAIL                  LLLOYD                01-Jan-87
+
+     The command 'DIR/NEW' will list just unread messages.
+
+
+Reading messages
+
+     In order to read messages in a folder, the user may type
+the read command or he/she may simply type the number of the
+message he wishes to read.  The message numbers can be acquired
+by doing the 'DIRECTORY' command.  If the user hits a carriage
+return with no input whatsoever,  BULLETIN will type the first
+message in the folder, or if there are new messages present, it
+will type the first new message in the folder.
+
+     If a folder contains the above messages (as seen by the
+'Directory' command) then these messages can be read by:
+
+BULLETIN> READ
+and BULLETIN would respond:
+
+Message number:  1                       PUBLIC_ANNOUNCEMENTS
+Description: CHRISTMAS PARTY
+Date:  26-JUN-1988 8:08:40   Expires:  1-JAN-1989 08:08:40
+
+...Body of message.....
+
+     Should the user only wish to see message number 3, he can
+enter the 'READ' command with the message number as a parameter.
+for example:
+
+BULLETIN> READ 3
+
+     There are three other useful commands that can be used at
+the 'BULLETIN>' prompt when reading messages. These are:
+
+BACK - Read the message preceding the message currently being
+read.
+
+CURRENT - Start reading the current message at the top.  This is
+useful for someone who is reading a message and wishes to reread
+it from the beginning.
+
+NEXT - Start reading from the beginning of the next message.
+This is handy if the user is reading a very long message and
+wants to skip to the next one.
+
+Saving the interesting stuff.
+
+     If the user sees something which he/she wants a copy of,
+the extract command can be use to write an ASCII copy of the
+message into a file.  This command works on the current message
+being read.  It requires the name of the file into which to save
+the message.  If the file name is not given, the user will be
+prompted for it.  For example:
+
+BULLETIN>  Read 2
+
+********** Message on Screen ********
+
+A person could then type
+BULLETIN> extract
+file:  FV.TXT
+BULLETIN>
+
+BULLETIN has now saved the contents of message number 2 into the
+file name 'FV.txt'.
+     If the file to which the user is writing already exists,
+BULLETIN will append the message to the file.  The user can
+force BULLETIN to write a new file containing only the message
+being saved by using the '/new' qualifier in the 'extract'
+command.  These messages can then be sent to other users, or
+downloaded for use in Wordperfect.  (See "Mail on the Vax", or
+"Transferring a file between a PC and the VAX").
+
+This command may be useful if you wish to transfer the message to
+your PC, perhaps using a BITNET journal message as a reference in
+a paper. Once the file is saved, you can transfer it to a PC by
+following the instructions in the handout 'Transferring files
+from the PC to the VAX of from the VAX to a PC".
+
+Adding messages
+     A user may add a message to a folder by selecting the
+folder and then using the 'ADD' command.  This is provided that
+the user is adding the message to a public folder.  The user has
+the option of giving the 'ADD' command and typing a message using
+the VAX editor or uploading a message from your PC (see
+documentation), or add a message you have extracted from VAX
+mail.  BULLETIN will prompt for the expiration date and subject
+line.  It will then add the text of the file as the body of the
+message. To add a message that is stored in a file (from MAIL or
+from your PC, for example) type:
+
+          ADD filename
+
+If the user does not specify a file name, he/she will be
+prompted to enter the body of the message.  The user may also
+use the EDT text editor by issuing the command with the
+'/EDIT'option.
+
+For example:
+BULLETIN> sel PUBLIC_ANNOUNCEMENTS
+          folder has been set to PUBLIC_ANNOUNCEMENTS
+BULLETIN> ADD MESS.TXT
+
+IT IS 10-JUL-1988 12:41:06.15.  SPECIFY WHEN THE MESSAGE SHOULD
+EXPIRE:  ENTER ABsolute TIME:  <DD-MMM-YYYY]HH:MM:SS OR DELTA
+TIME: DDD HH:MM:SS
+
+A user then type the date of expiration and press the 'return'
+button.  The time input may be ignored. For example, typing:
+20-JUL-1988 or type "10" - for ten days in the future.
+
+BULLETIN responds:
+ENTER DESCRIPTION HEADER.  LIMIT HEADER TO 53 CHARACTERS.
+
+Now the user may enter the subject of the message.
+
+BULLETIN>
+
+The above session adds the text in the file 'mess.txt' as the
+next message in the PUBLIC_ANNOUNCEMENTS Folder.  The message
+will be deleted automatically on the 20th of July as requested
+by the user adding the message.
+
+Asking BULLETIN to notify you of new messages upon logging in.
+
+     If the user wishes to get notification on login when new
+messages are in a folder, he should use the 'READNEW' option.
+This command does not force the reader to reading new messages,
+only gives notification.  To do this, 'SELECT' each folder you
+are interested in and do a 'SET READNEW' command while set to
+that folder.
+
+Example:
+
+BULLETIN> Select PUBLIC_ANNOUNCEMENTS
+folder has been set to PUBLIC_ANNOUNCEMENTS
+BULLETIN> SET READNEW
+
+Alternately, you may type SET SHOWNEW. This will just display a
+message notifying you that there are new messages.
+
+Mailing a BULLETIN message
+
+     A user may directly mail another user a message found in the
+BULLETIN.  While reading the message that he/she desires to send,
+at the 'BULLETIN>' type 'MAIL'.  The Vax will then ask to whom
+you wish to send the information too.
+
+Check the BULLETIN DISCUSSION folder on ALPHA for new additions.
+If you have comments or questions about BULLETIN, leave them
+there.
+$eod 
+$copy/log sys$input INSTRUCT.TXT
+$deck
+This message is being displayed by the BULLETIN facility.  This is a non-DEC
+facility, so it is not described in the manuals.  Messages can be submitted by
+using the BULLETIN command.  System messages, such as this one, are displayed
+in full, but can only be entered by privileged users.  Non-system messages can
+be entered by anyone, but only their topics will be displayed at login time,
+and will be prompted to optionally read them.  (This prompting feature can be
+disabled).  All bulletins can be reread at any time unless they are deleted or
+expire.  For more information, see the on-line help (via HELP BULLETIN). 
+$eod 
+$copy/log sys$input NEWS.TXT
+$deck
+BULLETIN has the capability to read and post messages  to  USENET  NEWS  in  a
+client  mode.  I realize that there are many NEWS readers, some with much more
+elegant interfaces.  However, I elected to modify BULLETIN for  the  following
+reason:   We have many decnet nodes, but only several are internet nodes.  Our
+only access  to  a  news  server  was  via  internet.    In  order  for  those
+non-internet  nodes  to read USENET, the only method that seemed available was
+to run a NEWS server program on one of our own internet nodes so that it could
+be accessible via decnet.  I did not want to do that, as that requires storing
+the news groups on disk, and I do not have the room for that.   I  thus  added
+the  ability  in  BULLETIN  (actually  BULLCP) so that it acts as as a gateway
+between decnet and tcp for NEWS.  This method does not  require  spawning  any
+processes,  since the detached process BULLCP is always present, so the access
+is very fast.  Also, since BULLETIN uses a shared database to  store  info  on
+the  NEWS  groups and periodically updates it, there is no need for that to be
+done when a user accesses the NEWS groups.  Several other NEWS readers do this
+when you run them, which is why they take a long time to start up.  It is also
+possible to feed NEWS groups into  a  "real"  BULLETIN  folder,  so  that  the
+messages are saved on disk (see the file NEWS_TO_FOLDER.TXT). 
+
+Presently, BULLETIN can be used with  either  UCX,  MULTINET,  or  CMU  TCP/IP
+packages  (and of course DECNET) for reading NEWS.  Support for other packages
+can be added if I can find sites willing to beta test the  interface  for  me.
+The  source  for  the  TCP  interface  is in C rather than FORTRAN because the
+MULTINET include files are in C. However, if you do not have C, I will be glad
+to send the object for it (or to even possibly rewrite the code in FORTRAN). 
+
+The instructions for installation are as follows.  Define BULL_NEWS_SERVER  to
+be a system logical name pointing to either your internet or decnet NEWS node.
+If it is decnet, simply specify the decnet node name, i.e. 
+
+	$ DEFINE/SYSTEM BULL_NEWS_SERVER NERUS
+
+BULLETIN decides to use DECNET rather than TCP access based on the node  name.
+If it does not have any periods in it, then it assumes it is a DECNET node. 
+
+In our cluster, we usually have one node which is an internet  node,  and  the
+rest  non-internet  nodes.    If  you have a similar situation, you'll have to
+create a startup procedure that defines BULL_NEWS_SERVER to  be  the  internet
+news  server  address  only  on  the  node (or nodes) on the cluster that have
+actually internet access.  The other nodes will have BULL_NEWS_SERVER  defined
+as the decnet node name that BULLCP is running on in the cluster.  (Of course,
+BULLCP will have to be running on a node with internet access.)
+
+NOTE: If you want to disable the gateway feature, then before starting BULLCP,
+define the logical name: 
+
+	$ DEFINE/SYSTEM BULL_NO_NEWS_GATEWAY "TRUE"
+
+Defining this will only shut off the gateway.  BULLETIN will still be  allowed
+to read NEWS from the local node as long as BULL_NEWS_SERVER is defined. 
+
+You can also specify that BULLCP is only to act as a NEWS gateway.  This is to
+allow  adding the news gateway to an INTERNET site that you have DECNET access
+to, but which does not want to make use of any of the other BULLETIN features.
+You would specify the following command before starting BULLCP: 
+
+	$ DEFINE/SYSTEM BULL_NEWS_GATEWAY_ONLY "TRUE"
+
+It is also possible for BULLETIN to access news groups  that  are  located  on
+other  news  servers than the one specified by BULL_NEWS_SERVER.  This is done
+by creating the  file  BULL_DIR:BULL_ALT_NEWS.LIS  and  adding  a  line  which
+containsthe  name  of  the  news group and the news server where it's located.
+The format is news-group-name:news-server-name.
+
+In order to post messages, BULLETIN needs to know the internet nodename of the
+local host.  This is done automatically for nodes running MULTINET.  For other
+nodes, BULLETIN attempts to  translate  the  logical  name  ARPANET_HOST_NAME,
+INTERNET_HOST_NAME, and MX_NODE_NAME.  If you are on a DECNET node that is not
+on INTERNET (and is not part of a cluster which has an INTERNET address),  but
+you are accessing NEWS via DECNET, you can specify the hostname as follows: 
+
+     $ DEFINE/SYSTEM INTERNET_HOST_NAME "%localhost@internet-address"
+
+Where "localhost" is your local decnet hostname, and "internet-address" is the
+internet address of the gateway node. 
+
+The local time zone is detected by looking at  the  following  logical  names:
+LISP$TIME_ZONE,  MULTINET_TIMEZONE,  or  PMDF_TIMEZONE.    (LISP$TIME_ZONE  is
+defined if you have LISP installed.)
+
+The name of the organization is included in the header of  the  NEWS  message.
+This can be anything, but usually is the company or university name.  This can
+be hardcoded into the source by putting in BULLNEWS.INC, or  by  defining  the
+system logical name BULL_NEWS_ORGANIZATION. 
+
+The name of the mail protocol to use for responding by mail to  NEWS  messages
+can  also  be  either hardcoded by putting in BULLNEWS.INC, or by defining the
+system logical name BULL_NEWS_MAILER. 
+
+After installing the new BULLETIN, execute the command NEWS, which asks for  a
+list  of  all the news groups.  Because this is the first time it is executed,
+it will cause a load of all the remote news groups  into  a  local  data  base
+(BULL_DIR:BULLNEWS.DAT). This will take several minutes to do.  It is the only
+time that this load will be  done  interactively.    Afterwards,  BULLCP  will
+periodically  update  the data base.  For this reason, it is highly recommeded
+that BULLCP be installed. BULLCP will update NEWS every hour.  If you want  to
+change  this frequency, define the logical name BULL_NEWS_UPDATE to the number
+of minutes in between updates, i.e. DEFINE/SYSTEM BULL_NEWS_UPDATE "30" for 30
+minutes.    NOTE:  BULLCP  will create a subprocess BULLCP NEWS which does the
+update.  You can watch how long it takes for this to run in order to determine
+if you want to change the update period). 
+
+Due to long news group names recently created, you must do the following, or
+else those news groups will not be seen.  After BULLNEWS.DAT is created, do
+the following:
+
+$ ANAL/RMS/FDL/OUT=FIX.FDL BULL_DIR:BULLNEWS.DAT
+
+Edit FIX.FDL and find the first line which says
+	DUPLICATES no
+and change it to
+	DUPLICATES yes
+
+Then type:
+
+$ CONVERT BULL_DIR:BULLNEWS.DAT BULL_DIR:BULLNEWS.DAT/FDL=FIX.FDL
+
+Also, it is suggested that you run OPTIMIZE_RMS.COM on it, as it will cause the
+file to be compressed and will allow updates to run much faster (factor of 5 or
+more). 
+
+Never delete BULLNEWS.DAT.  There is no reason to ever  do  so,  and  it  will
+cause subscribed users to be subscribed to the wrong news groups. 
+
+WARNING: One user discovered that his server (using bnews?) had  a  bug  which
+caused  the updates to cause bogus "new messages" notifications for subscribed
+NEWS group when entering BULLETIN.    If  you  experience  this  problem,  try
+defining  the  system  logical name BULL_SPECIAL_NEWS_UPDATE.  This will cause
+the update to use a different algorithm which should  eliminate  the  problem,
+although it requires much more time to execute. 
+
+If you have any problems or questions, please let me know.
+									MRL
+$eod 
+$copy/log sys$input NEWS_TO_FOLDER.TXT
+$deck
+It is possible to automatically have messages from a news group be fed into  a
+real  folder, and visa versa.  This allows BULLETIN messages to be shared with
+a news group, thus giving access to such messages to people who  do  not  have
+access  to  BULLETIN.   This can also be combined with email access for people
+who have neither BULLETIN nor news group access. 
+
+To associate a folder with a news group, place the name of the news group into
+the  folder  description  surrounded  by  <>, i.e. <misc.test>.  It must be in
+lower case.  (Other text is allowed in the description, i.e. "THIS IS  A  TEST
+FOLDER  <misc.test>".)  When messages are added the folder, they are also sent
+to the news group, and new messages from the group are posted  to  the  folder
+(via  the  BULLCP  process  which wakes up on a periodic basis).  Whenever you
+modify the folder description and specify the news group  name,  you  will  be
+prompted  as  to  whether  you  want  to initializee the news group counter to
+either load all the messages present in the news group, or to load  only  news
+messages that appear there. 
+
+Messages posted to the news group from such a folder have a  special  line  in
+their  header  indicating  they were sent from that node using bulletin.  When
+bulletin feeds new postings back to the folder, it will see that  header  line
+and  also see that it was posted from that node, and thus will avoid adding it
+to the folder (and thus creating a duplicate message).  Note that messages are
+added  to  the  news  group  via  the  BULLCP process, so they will not appear
+immediately after being added to the folder. 
+
+If you are modifying an existing folder to make  it  associated  with  a  news
+group, and if you want to copy any existing messages in the folder to the news
+group, you can do that by using the command COPY/ORIGINAL/LOCAL and specifying
+the  news  group  as the destination.  /ORIGINAL will cause the original owner
+names and dates to be preserved (note, however, that dates older than 14  days
+in  the  past are not usually accepted by the news server, so dates older than
+that will be changed to the present date).  /LOCAL  will  create  the  special
+header  line in the messages to prevent BULLCP from adding those messages back
+to the folder from the news group.  /ALL can be  specified  to  copy  all  the
+messages in the folder. 
+
+If you create a remote folder that points to a folder that has  a  news  group
+associated  with  it,  you  do  not  have  to  specify  the  news group in the
+description of the remote node.  However, on the  node  on  which  the  folder
+actually  exists,  the  news  group  has be a stored news group, i.e. you must
+issue the command SET NEWS/STORED for that news group. 
+
+When a news group is specified for a folder, it is still possible to associate
+an  email  address  for  the messages to be sent to in the folder description.
+You do this by using [] to enclose the address rather than the usual <>,  i.e.
+[mrl@pfc.mit.edu]  See  help in BULLETIN on the command CREATE/DESCRIPTION for
+more info about associated email addresses.  Note that  these  features  allow
+you to create a full gateway between a news group and a mailing list. 
+$eod 
+$copy/log sys$input NONSYSTEM.TXT
+$deck
+Non-system bulletins (such as this) can be submitted by any user.  Users are
+alerted at login time that new non-system bulletins have been added, but only
+their topics are listed.  Optionally, users can be prompted at login time to
+see if they wish to read the bulletins.  When reading the bulletins in this
+manner, the bulletins can optionally be written to a file.  If you have the
+subdirectory [.BULL] created, BULLETIN will use that directory as the default
+directory to write the file into.
+
+A user can disable this prompting featuring by using BULLETIN as follows: 
+
+$ BULLETIN
+BULLETIN> SET NOREADNEW
+BULLETIN> EXIT
+
+Afterwords, the user will only be alerted of the bulletins, and will have to
+use the BULLETIN utility in order to read the messages.
+$eod 
+$copy/log sys$input WRITEMSG.TXT
+$deck
+BULLETIN contains subroutines for writing a message directly to a folder.  This
+would be useful for someone who is using the BBOARD feature, but wants to avoid
+the extra overhead of having the message sent to an account as MAIL, and then
+have BULLCP read the mail.  It is better if the network mail could be written
+directly to the folder bypassing VMS MAIL, as it reduces a lot of cpu overhead.
+
+Call INIT_MESSAGE_ADD to initiate a message addition.
+Call WRITE_MESSAGE_LINE to write individual message lines.
+Call FINISH_MESSAGE_ADD to complete a message addition.
+
+Calling formats:
+
+	CALL INIT_MESSAGE_ADD(IN_FOLDER,IN_FROM,IN_DESCRIP,IER)
+C
+C  INPUTS:
+C	IN_FOLDER  - Character string containing folder name
+C	IN_FROM	   - Character string containing name of owner of message.
+C		     If empty, the default is the owner of the process.
+C	IN_DESCRIP - Character string containing subject of message.
+C		     If empty, the message is searched for a line
+C		     which starts with "Subj:" or "Subject:".
+C  OUTPUTS:
+C	IER - Error status.  True if properly connected to folder.
+C		False if folder not found.
+C
+
+	CALL WRITE_MESSAGE_LINE(BUFFER)
+C
+C  INPUTS:
+C	BUFFER - Character string containing line to be put into message.
+C
+
+	CALL FINISH_MESSAGE_ADD
+C
+C  NOTE:  Only should be run if INIT_MESSAGE_ADD was successful.
+C
+$eod 
diff --git a/decus/vmslt98a/bulletin/bullet2.com b/decus/vmslt98a/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..ea6c209266707fefd3817ba227deb3b906c098f5
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullet2.com
@@ -0,0 +1,1701 @@
+$set nover
+$copy/log sys$input BOARD_DIGEST.COM
+$deck
+$!
+$! BOARD_DIGEST.COM
+$!
+$! Command file invoked by folder associated with a BBOARD which is
+$! is specified with /SPECIAL.  It will convert "digest" mail and
+$! split it into separate messages.  This type of mail is used in
+$! certain Arpanet mailing lists, such as TEXHAX and INFO-MAC.
+$!
+$ FF[0,8] = 12			! Define a form feed character
+$ SET PROTECT=(W:RWED)/DEFAULT
+$ SET PROC/PRIV=SYSPRV
+$ USER := 'F$GETJPI("","USERNAME")
+$ EXTRACT_FILE = "BULL_DIR:" + "''USER'" + ".TXT"
+$ DEFINE/USER EXTRACT_FILE BULL_DIR:'USER'
+$ MAIL
+READ
+EXTRACT EXTRACT_FILE
+DELETE
+$ OPEN/READ INPUT 'EXTRACT_FILE'
+$ OPEN/WRITE OUTPUT 'EXTRACT_FILE'
+$ READ INPUT FROM_USER
+$AGAIN:
+$ READ/END=ERROR INPUT BUFFER
+$ IF F$EXTRACT(0,3,BUFFER) .NES. "To:" THEN GOTO SKIP
+$ USER = F$EXTRACT(4,F$LEN(BUFFER),BUFFER)
+$ GOTO AGAIN1
+$SKIP:
+$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN
+$AGAIN1:
+$ READ/END=ERROR INPUT BUFFER
+$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN1
+$ FROM = " "
+$ SUBJ = " "
+$NEXT:
+$ READ/END=EXIT INPUT BUFFER
+$FROM:
+$ IF F$EXTRACT(0,5,BUFFER) .NES. "From:" THEN GOTO SUBJECT
+$ FROM = BUFFER 
+$ GOTO NEXT
+$SUBJECT:
+$ IF F$EXTRACT(0,8,BUFFER) .NES. "Subject:" THEN GOTO NEXT
+$ SUBJ = BUFFER - "Subject:"
+$F2:
+$ IF F$LENGTH(SUBJ) .EQ. 0 THEN GOTO WRITE
+$ IF F$EXTRACT(0,1,SUBJ) .NES. " " THEN GOTO WRITE
+$ SUBJ = F$EXTRACT(1,F$LENGTH(SUBJ),SUBJ)
+$ GOTO F2
+$WRITE:
+$ WRITE OUTPUT FROM_USER
+				! Write From: + TAB + USERNAME
+$ WRITE OUTPUT "To:	" + USER
+				! Write To: + TAB + BBOARDUSERNAME
+$ WRITE OUTPUT "Subj:	" + SUBJ
+				! Write Subject: + TAB + mail subject
+$ WRITE OUTPUT ""		! Write one blank line
+$ IF FROM .NES. " " THEN WRITE OUTPUT FROM
+$READ:
+$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
+$ IF F$EXTRACT(0,15,BUFFER) .EQS. "---------------" THEN GOTO READ1
+$ WRITE OUTPUT BUFFER
+$ GOTO READ
+$READ1:
+$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
+$ IF F$LOCATE(":",BUFFER) .EQ. F$LENGTH(BUFFER) THEN GOTO READ1
+$ WRITE OUTPUT FF
+$ FROM = " "
+$ SUBJ = " "
+$ GOTO FROM
+$EXIT:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ PUR 'EXTRACT_FILE'
+$ EXIT
+$ERROR:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ DELETE 'EXTRACT_FILE';
+$eod 
+$copy/log sys$input BOARD_SPECIAL.COM
+$deck
+$!
+$! BOARD_SPECIAL.COM
+$!
+$! Command file invoked by folder associated with a BBOARD which is
+$! is specified with /SPECIAL.  This can be used to convert data to
+$! a message via a different means than the VMS mail.  This is done by
+$! converting the data to look like output created by the MAIL utility,
+$! which appears as follows:
+$!
+$!	First line is 0 length line.
+$!	Second line is "From:" followed by TAB followed by incoming username
+$!	Third line is "To:" followed by TAB followed by BBOARD username
+$!	Fourth line is "Subj:" followed by TAB followed by subject
+$!	The message text then follows.
+$!	Message is ended by a line containing a FORM FEED.
+$!
+$! This command file should be put in the BBOARD_DIRECTORY as specified
+$! in BULLFILES.INC.  You can also have several different types of special
+$! procedures.  To accomplish this, rename the file to the BBOARD username.
+$! i.e. if you specify SET BBOARD FOO/SPECIAL, you could name the file
+$! FOO.COM and it will execute that rather than BOARD_SPECIAL.COM.
+$!
+$! The following routine is the one we use to convert mail from a non-DEC
+$! mail network.  The output from this mail is written into a file which
+$! is slightly different from the type outputted by MAIL.
+$!
+$! (NOTE: A username in the SET BBOARD command need only be specified if
+$! the process which reads the mail requires that the process be owned by
+$! a specific user, which is the case for this sample, and for that matter
+$! when reading VMS MAIL.  If this is not required, you do not have to
+$! specify a username.)
+$!
+$ USERNAME := 'F$GETJPI("","USERNAME")'		! This trims trailing spaces
+$ IF F$SEARCH("MFE_TELL_FILES:"+USERNAME+".MAI") .EQS. "" THEN EXIT
+$ SET DEFAULT BULL_DIR:	! BULLETIN looks for text in BBOARD directory
+$ SET PROTECT=(W:RWED)/DEFAULT
+$ IF F$SEARCH("MFEMSG.MAI") .NES. "" THEN -
+  DELETE MFEMSG.MAI;*		! Delete any leftover output files.
+$ MSG := $MFE_TELL: MESSAGE
+$ DEFINE/USER SYS$COMMAND SYS$INPUT
+$ MSG				! Read MFENET mail
+copy * MFEMSG
+delete *
+exit
+$ FF[0,8] = 12			! Define a form feed character
+$ OPEN/READ/ERROR=EXIT INPUT MFEMSG.MAI
+$ OUTNAME = USERNAME+".TXT"	! Output file will be 'USERNAME'.TXT
+$ OPEN/WRITE OUTPUT 'OUTNAME'
+$ READ/END=END INPUT DATA		! Skip first line in MSG output
+$HEADER:
+$ FROM = ""
+$ SUBJ = ""
+$ MFEMAIL = "T"
+$NEXTHEADER:
+$ IF (FROM.NES."") .AND. (SUBJ.NES."") THEN GOTO SKIPHEADER
+$ READ/END=END INPUT DATA		! Read header line in MSG output
+$ IF DATA .EQS. "" THEN GOTO SKIPHEADER	! Missing From or Subj ??
+$ IF FROM .NES. "" THEN GOTO SKIPFROM
+$ IF F$LOCATE("From: ",DATA) .NES. 0 THEN GOTO 10$
+$ MFEMAIL = "F"
+$ FROM= F$EXTRACT(6,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$10$:
+$ IF F$LOCATE("Reply-to: ",DATA) .NES. 0 THEN GOTO 20$
+$ MFEMAIL = "F"
+$ FROM= F$EXTRACT(10,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$20$:
+$ IF F$LOCATE("From ",DATA) .NES. 0 THEN GOTO SKIPFROM
+$ FROM= F$EXTRACT(5,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$SKIPFROM:
+$ IF SUBJ .NES. "" THEN GOTO SKIPSUBJ
+$ IF F$LOCATE("Subject",DATA) .NES. 0 THEN GOTO SKIPSUBJ
+$ SUBJ= F$EXTRACT(F$LOCATE(": ",DATA)+2,F$LENGTH(DATA),DATA)
+$ GOTO NEXTHEADER
+$SKIPSUBJ:
+$ GOTO NEXTHEADER
+$SKIPHEADER:
+$ WRITE OUTPUT "From:	" + FROM
+				! Write From: + TAB + USERNAME
+$ WRITE OUTPUT "To:	" + USERNAME
+				! Write To: + TAB + BBOARDUSERNAME
+$ WRITE OUTPUT "Subj:	" + SUBJ
+				! Write Subject: + TAB + mail subject
+$ WRITE OUTPUT ""		! Write one blank line
+$ IF (DATA.EQS."") .OR. MFEMAIL THEN GOTO SKIPBLANKS
+$50$:
+$ READ/END=END INPUT DATA		! Skip rest of main header
+$ IF DATA .NES. "" THEN GOTO 50$
+$60$:
+$ READ/END=END INPUT DATA		! Skip all of secondary header
+$ IF DATA .NES. "" THEN GOTO 60$
+$SKIPBLANKS:
+$ READ/END=END INPUT DATA		! Skip all blanks
+$ IF DATA .EQS. "" THEN GOTO SKIPBLANKS
+$NEXT:				! Read and write message text
+$ WRITE OUTPUT DATA
+$ IF DATA .EQS. FF THEN GOTO HEADER
+			! Multiple messages are seperated by form feeds
+$ READ/END=END INPUT DATA
+$ GOTO NEXT
+$END:
+$ CLOSE INPUT
+$ CLOSE OUTPUT
+$ DELETE MFEMSG.MAI;
+$EXIT:
+$ EXIT
+$eod 
+$copy/log sys$input BULLCOM.CLD
+$deck
+!
+! BULLCOM.CLD
+!
+! VERSION 4/10/97
+!
+ 	MODULE BULLETIN_SUBCOMMANDS
+
+	DEFINE VERB ADD
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER BELL, NONNEGATABLE
+		QUALIFIER BROADCAST, NONNEGATABLE
+		DISALLOW NOT BROADCAST AND ALL
+		DISALLOW NOT BROADCAST AND BELL
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER CLUSTER, DEFAULT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT, NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		NONNEGATABLE
+		QUALIFIER LIST,DEFAULT
+		QUALIFIER LOCAL, NONNEGATABLE
+		DISALLOW LOCAL AND NOT BROADCAST
+		DISALLOW NODES AND SELECT_FOLDER
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		DISALLOW PERMANENT AND SHUTDOWN
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM, NONNEGATABLE
+	DEFINE VERB ATTACH
+		PARAMETER P1, LABEL=PROCESS, VALUE(TYPE=$FILE)
+		QUALIFIER PARENT
+		DISALLOW NOT PARENT AND NOT PROCESS
+		DISALLOW PARENT AND PROCESS
+	DEFINE VERB BACK
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB CHANGE
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER GENERAL, NONNEGATABLE
+		QUALIFIER HEADER, NONNEGATABLE
+		QUALIFIER NEW,NONNEGATABLE
+		QUALIFIER NUMBER, VALUE(TYPE=$FILE,REQUIRED)
+		QUALIFIER OWNER, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM,NONNEGATABLE
+		QUALIFIER TEXT, NONNEGATABLE
+		DISALLOW ALL AND NUMBER
+		DISALLOW NEW AND NOT EDIT
+		DISALLOW SYSTEM AND GENERAL
+		DISALLOW PERMANENT AND SHUTDOWN
+		DISALLOW PERMANENT AND EXPIRATION
+		DISALLOW SHUTDOWN AND EXPIRATION
+		DISALLOW SUBJECT AND HEADER
+	DEFINE VERB COPY
+		PARAMETER P1, LABEL=FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER ALL
+		QUALIFIER LOCAL
+		QUALIFIER MERGE
+		QUALIFIER ORIGINAL
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB CREATE
+		QUALIFIER ADD_ONLY, NONNEGATABLE
+		QUALIFIER ALWAYS, NONNEGATABLE
+		QUALIFIER BRIEF, NONNEGATABLE
+		QUALIFIER COMPRESS, NONNEGATABLE
+		QUALIFIER COPY, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER DESCRIPTION, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER ID, NONNEGATABLE
+!
+! Add ,DEFAULT to the end of the following line if you want CREATE to be
+! a privileged command.  NOTE: Make sure that BULL_DIR:BULLUSER.DAT
+! has the following protection:  (RWED,RWED,,)
+!
+		QUALIFIER NEEDPRIV, NONNEGATABLE
+		QUALIFIER NEWS
+		QUALIFIER NODE, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER NOTIFY, NONNEGATABLE
+		QUALIFIER OWNER, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER POST_ONLY, NONNEGATABLE
+		QUALIFIER PRIVATE, NONNEGATABLE
+		QUALIFIER READNEW, NONNEGATABLE
+		QUALIFIER REMOTENAME, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SEMIPRIVATE, NONNEGATABLE
+		QUALIFIER SHOWNEW, NONNEGATABLE
+		QUALIFIER SYSTEM, NONNEGATABLE
+		PARAMETER P1, LABEL=CREATE_FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		DISALLOW ID AND NOT OWNER
+		DISALLOW PRIVATE AND SEMIPRIVATE
+		DISALLOW BRIEF AND READNEW
+		DISALLOW SHOWNEW AND READNEW
+		DISALLOW BRIEF AND SHOWNEW
+		DISALLOW NODE AND (NOTIFY OR PRIVATE OR SEMIPRIVATE)
+		DISALLOW REMOTENAME AND NOT NODE
+		DISALLOW POST_ONLY AND ADD_ONLY
+	DEFINE VERB CURRENT
+		QUALIFIER EDIT
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB DELETE
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER IMMEDIATE,NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER FORCE
+		QUALIFIER LOCAL
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		QUALIFIER REASON, VALUE(REQUIRED)
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+		DISALLOW NOT SUBJECT AND (NODES OR SELECT_FOLDER)
+		DISALLOW NODES AND SELECT_FOLDER
+	DEFINE TYPE SEARCH_MATCHES
+	   	KEYWORD AND
+	   	KEYWORD OR
+	      		DEFAULT
+	   	KEYWORD XOR
+	DEFINE VERB DIRECTORY
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER ALL
+		QUALIFIER CONTINUE
+		QUALIFIER NEWS, SYNTAX=DIRECTORY_NEWS, NONNEGATABLE
+		QUALIFIER END, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER EXPIRATION
+		QUALIFIER EXTRACT, VALUE(TYPE=$FILE,REQUIRED)
+		QUALIFIER FEEDBACK
+		QUALIFIER FF
+		QUALIFIER FO, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+		QUALIFIER FOLDER, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+                QUALIFIER GROUP, VALUE(REQUIRED,LIST)
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW
+		QUALIFIER NOTIFY, DEFAULT
+		QUALIFIER PRINT
+		QUALIFIER QUEUE, VALUE(DEFAULT=SYS$PRINT), NONNEGATABLE
+                QUALIFIER FORM, VALUE, NONNEGATABLE
+		QUALIFIER MATCH, VALUE(DEFAULT="OR",TYPE=SEARCH_MATCHES)
+		QUALIFIER NOW
+		QUALIFIER OUTPUT,VALUE(REQUIRED,TYPE=$FILE)
+		QUALIFIER POST, DEFAULT
+		QUALIFIER START, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER ROTATE
+		QUALIFIER SEARCH, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SUBJECT, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER FROM, VALUE(REQUIRED), NONNEGATABLE
+                QUALIFIER NEGATED
+                DISALLOW GROUP AND
+			 NOT (SUBJECT OR SEARCH OR FROM OR NOREPLIES)
+                DISALLOW NEGATED AND 
+			 NOT (SUBJECT OR SEARCH OR FROM OR NOREPLIES)
+		DISALLOW (SUBJECT AND SEARCH) OR (SEARCH AND REPLY)
+		DISALLOW (FROM AND SUBJECT) OR (FROM AND NOREPLIES)
+		DISALLOW (NOREPLIES AND SUBJECT) OR (REPLY AND NOREPLIES)
+		DISALLOW (REPLY AND SUBJECT) OR (REPLY AND FROM)
+		DISALLOW (REPLY OR SUBJECT OR SEARCH OR FROM) AND
+			 (MARKED OR SEEN OR UNMARKED OR UNSEEN)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+		DISALLOW ALL AND (MARKED OR SEEN OR UNMARKED OR UNSEEN)
+		DISALLOW (NEW AND SINCE) OR (START AND NEW) OR (START AND SINCE)
+	DEFINE SYNTAX DIRECTORY_NEWS
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER NEWS, DEFAULT, NONNEGATABLE
+		QUALIFIER DEFAULT
+		QUALIFIER PERMANENT
+		QUALIFIER SUBSCRIBE
+		QUALIFIER FOLDER
+		QUALIFIER NEWGROUPS
+		QUALIFIER ALL
+		QUALIFIER STORED
+		QUALIFIER CLASS
+		QUALIFIER COUNT
+	DEFINE SYNTAX DIRECTORY_FOLDER
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER DESCRIBE
+		QUALIFIER FOLDER, DEFAULT
+		QUALIFIER NEWS, NONNEGATABLE
+	DEFINE VERB E				! EXIT command.
+	DEFINE VERB EX				! EXIT command.
+	DEFINE VERB EXIT			! EXIT command.
+	DEFINE VERB EXCLUDE
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL
+		QUALIFIER LIMIT, VALUE
+		QUALIFIER SUBJECT
+		DISALLOW FULL AND (ALL OR P1 OR FROM OR SUBJECT)
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB EXTRACT
+		PARAMETER P1, LABEL=EXTRACT, VALUE(TYPE=$FILE)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER ALL
+		QUALIFIER FF
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW, NONNEGATABLE
+		QUALIFIER ROTATE
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB FILE
+		PARAMETER P1, LABEL=EXTRACT, VALUE(TYPE=$FILE)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER ALL
+		QUALIFIER FF
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NEW, NONNEGATABLE
+		QUALIFIER ROTATE
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB FIRST
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB FORWARD
+		PARAMETER P1, LABEL=RECIPIENTS, PROMPT="Recipients"
+		VALUE(REQUIRED,IMPCAT,LIST)
+		QUALIFIER EDIT, NONNEGATABLE
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB HELP
+		PARAMETER P1, LABEL=HELP_FOLDER, VALUE(TYPE=$REST_OF_LINE)
+	DEFINE VERB INCLUDE
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL 
+		QUALIFIER LIMIT, VALUE
+		QUALIFIER SUBJECT, DEFAULT
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB THREAD
+		PARAMETER P1
+		QUALIFIER ALL
+		QUALIFIER DISABLE 
+		QUALIFIER FROM
+		QUALIFIER FULL 
+		QUALIFIER LIMIT, VALUE, NONNEGATABLE
+		QUALIFIER SUBJECT, DEFAULT
+		DISALLOW ALL AND NOT DISABLE
+	DEFINE VERB INDEX
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER EXPIRATION
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER FOLDER, SYNTAX=DIRECTORY_FOLDER, NONNEGATABLE
+		QUALIFIER NEW, DEFAULT
+		QUALIFIER MATCH, VALUE(DEFAULT="OR",TYPE=SEARCH_MATCHES)
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER RESTART
+		QUALIFIER SEARCH, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER SET , DEFAULT
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SUBSCRIBE
+		QUALIFIER PERMANENT
+		QUALIFIER NEGATED
+		QUALIFIER FROM, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SUBJECT, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER START, VALUE(REQUIRED,TYPE=$NUMBER), NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		DISALLOW (NEW AND SINCE) OR (START AND NEW) OR (START AND SINCE)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB LAST
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+		QUALIFIER ROTATE
+	DEFINE VERB MAIL
+		PARAMETER P1, LABEL=RECIPIENTS, PROMPT="Recipients"
+		VALUE(REQUIRED,IMPCAT,LIST)
+		QUALIFIER EDIT, NONNEGATABLE
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB MARK
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB MODIFY
+		QUALIFIER DESCRIPTION
+		QUALIFIER ID, NONNEGATABLE
+		QUALIFIER NAME, VALUE(REQUIRED)
+		QUALIFIER OWNER, VALUE(REQUIRED)
+		DISALLOW ID AND NOT OWNER
+	DEFINE VERB MOVE
+		PARAMETER P1, LABEL=FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+		PARAMETER P2, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER ALL
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER FORCE
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LOCAL
+		QUALIFIER MERGE
+		QUALIFIER NODES
+		QUALIFIER ORIGINAL
+		QUALIFIER IMMEDIATE,NONNEGATABLE,DEFAULT
+		DISALLOW ALL AND BULLETIN_NUMBER
+		DISALLOW FOLDER AND NODES
+	DEFINE VERB NEWS
+		PARAMETER P1, LABEL=MATCH_FOLDER
+		QUALIFIER NEWS, DEFAULT, NONNEGATABLE
+		QUALIFIER COUNT
+		QUALIFIER START, VALUE(REQUIRED), NONNEGATABLE
+		QUALIFIER SUBSCRIBE
+		QUALIFIER DEFAULT
+		QUALIFIER PERMANENT
+		QUALIFIER NEWGROUPS
+		QUALIFIER ALL
+		QUALIFIER STORED
+		QUALIFIER CLASS
+		DISALLOW CLASS AND (SUBSCRIBE OR START OR ALL OR STORED
+			 OR PERMANENT OR DEFAULT)
+		DISALLOW NEWGROUPS AND (SUBSCRIBE OR START OR ALL OR STORED
+					OR PERMANENT OR DEFAULT)
+		DISALLOW (DEFAULT AND PERMANENT) OR (DEFAULT AND SUBSCRIBE)
+		DISALLOW PERMANENT AND SUBSCRIBE
+	DEFINE VERB N
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+                QUALIFIER ROTATE
+	DEFINE VERB NEXT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER HEADER
+                QUALIFIER ROTATE
+	DEFINE VERB POST
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER EDIT
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST, DEFAULT
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER NOSIGNATURE
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+	DEFINE VERB PRINT
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER HEADER, DEFAULT
+		QUALIFIER NOTIFY, DEFAULT
+		QUALIFIER QUEUE, VALUE(DEFAULT=SYS$PRINT), NONNEGATABLE
+                QUALIFIER FORM, VALUE, NONNEGATABLE
+		QUALIFIER NOW
+		QUALIFIER CANCEL
+		QUALIFIER ALL
+		DISALLOW ALL AND BULLETIN_NUMBER
+	DEFINE VERB QUIT
+	DEFINE VERB READ
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$NUMBER)
+		QUALIFIER ALL
+		QUALIFIER EDIT
+		QUALIFIER HEADER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER NEW
+		QUALIFIER PAGE, DEFAULT
+		QUALIFIER POST, DEFAULT
+		QUALIFIER ROTATE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER THREADS
+		QUALIFIER UNSEEN, NONNEGATABLE
+		QUALIFIER SINCE,VALUE(DEFAULT="TODAY",TYPE=$DATETIME)
+		DISALLOW NEW AND SINCE
+		DISALLOW BULLETIN_NUMBER AND (ALL OR NEW OR SINCE)
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB REPLY
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER BELL, NONNEGATABLE
+		QUALIFIER BROADCAST, NONNEGATABLE
+		DISALLOW NOT BROADCAST AND ALL
+		DISALLOW NOT BROADCAST AND BELL
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER CLUSTER, DEFAULT
+		QUALIFIER EDIT, NEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT, NONNEGATABLE
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST,DEFAULT
+		QUALIFIER LOCAL
+		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
+		NONNEGATABLE
+		DISALLOW LOCAL AND NOT BROADCAST
+		DISALLOW NODES AND SELECT_FOLDER
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		QUALIFIER PERMANENT, NONNEGATABLE
+		QUALIFIER SHUTDOWN, NONNEGATABLE, VALUE
+		DISALLOW PERMANENT AND SHUTDOWN
+		QUALIFIER SUBJECT, NONNEGATABLE, VALUE(REQUIRED)
+		QUALIFIER SYSTEM, NONNEGATABLE
+	DEFINE VERB REMOVE
+		PARAMETER P1, LABEL=REMOVE_FOLDER, PROMPT="Folder"
+			VALUE(REQUIRED)
+	DEFINE VERB RESET
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE)
+		QUALIFIER CURRENT
+		DISALLOW CURRENT AND NUMBER
+	DEFINE VERB RESPOND
+		PARAMETER P1, LABEL=FILESPEC, VALUE(TYPE=$FILE)
+		QUALIFIER CC, VALUE(LIST,REQUIRED)
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE
+		QUALIFIER EXTRACT
+		QUALIFIER GROUPS, VALUE(LIST,REQUIRED)
+		QUALIFIER HEADER
+		QUALIFIER LIST
+		QUALIFIER SUBJECT, VALUE(REQUIRED)
+		QUALIFIER INDENT, VALUE(DEFAULT="->"), DEFAULT
+		QUALIFIER FOLLOWUP, VALUE(REQUIRED)
+		QUALIFIER NOSIGNATURE
+		DISALLOW GROUPS AND NOT LIST
+		QUALIFIER EDIT
+	DEFINE VERB SEARCH
+		PARAMETER P1, LABEL=SEARCH_STRING, VALUE(LIST) 
+		QUALIFIER EDIT
+		QUALIFIER FEEDBACK
+		QUALIFIER FOLDER, LABEL=SELECT_FOLDER, VALUE(REQUIRED,LIST)
+		QUALIFIER FROM
+                QUALIFIER GROUP, VALUE(REQUIRED,LIST)
+                QUALIFIER NEGATED
+		QUALIFIER NOREPLIES, NONNEGATABLE
+		QUALIFIER REPLY, NONNEGATABLE
+		QUALIFIER REVERSE
+		QUALIFIER START, VALUE(TYPE=$NUMBER)
+		QUALIFIER SUBJECT
+		QUALIFIER MATCH, VALUE(REQUIRED)
+		DISALLOW NOT (SEARCH_STRING OR REPLY) AND REVERSE
+		DISALLOW SEARCH_STRING AND REPLY
+		DISALLOW GROUP AND SELECT_FOLDER
+	DEFINE VERB SEEN
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+		QUALIFIER READ
+		DISALLOW (NUMBER AND (NEG READ OR READ))
+	DEFINE VERB SELECT
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE VERB SET
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER ID
+	DEFINE TYPE SET_OPTIONS
+		KEYWORD NODE, SYNTAX=SET_NODE
+		KEYWORD NONODE, SYNTAX = SET_NONODE
+		KEYWORD EXPIRE_LIMIT, SYNTAX=SET_EXPIRE
+		KEYWORD NOEXPIRE_LIMIT
+		KEYWORD GENERIC, SYNTAX=SET_GENERIC
+		KEYWORD NOGENERIC, SYNTAX=SET_GENERIC
+		KEYWORD LIBRARY, SYNTAX=SET_LIBRARY
+		KEYWORD LOGIN, SYNTAX=SET_LOGIN
+		KEYWORD NOLOGIN, SYNTAX=SET_LOGIN
+		KEYWORD NOBBOARD
+		KEYWORD BBOARD, SYNTAX=SET_BBOARD
+		KEYWORD NOBRIEF, SYNTAX=SET_NOFLAGS
+		KEYWORD BRIEF, SYNTAX=SET_FLAGS
+		KEYWORD NOSHOWNEW, SYNTAX=SET_NOFLAGS
+		KEYWORD SHOWNEW, SYNTAX=SET_FLAGS
+		KEYWORD NOREADNEW, SYNTAX=SET_NOFLAGS
+		KEYWORD READNEW, SYNTAX=SET_FLAGS
+		KEYWORD ACCESS, SYNTAX=SET_ACCESS
+		KEYWORD NOACCESS, SYNTAX=SET_NOACCESS
+		KEYWORD FOLDER, SYNTAX=SET_FOLDER
+		KEYWORD NOTIFY, SYNTAX=SET_FLAGS
+		KEYWORD NONOTIFY, SYNTAX=SET_NOFLAGS
+		KEYWORD PRIVILEGES, SYNTAX=SET_PRIVILEGES
+		KEYWORD DUMP
+		KEYWORD NODUMP
+		KEYWORD PAGE
+		KEYWORD NOPAGE
+		KEYWORD SYSTEM
+		KEYWORD NOSYSTEM
+		KEYWORD KEYPAD
+		KEYWORD NOKEYPAD
+		KEYWORD PROMPT_EXPIRE
+		KEYWORD NOPROMPT_EXPIRE
+		KEYWORD DEFAULT_EXPIRE, SYNTAX=SET_DEFAULT_EXPIRE
+		KEYWORD STRIP
+		KEYWORD NOSTRIP
+		KEYWORD DIGEST
+		KEYWORD NODIGEST
+		KEYWORD CONTINUOUS_BRIEF
+		KEYWORD NOCONTINUOUS_BRIEF
+		KEYWORD ALWAYS
+		KEYWORD NOALWAYS
+		KEYWORD COMPRESS
+		KEYWORD NOCOMPRESS
+		KEYWORD POST_ONLY
+		KEYWORD NOPOST_ONLY
+		KEYWORD ADD_ONLY
+		KEYWORD NOADD_ONLY
+		KEYWORD NEWS, SYNTAX=SET_NEWS 
+		KEYWORD ANONYMOUS
+		KEYWORD NOANONYMOUS
+		KEYWORD EXLIMIT,SYNTAX=SET_EXLIMIT
+		KEYWORD EXCLUDE
+		KEYWORD NOEXCLUDE
+		KEYWORD NAME,SYNTAX=SET_NAME
+		KEYWORD SUBSCRIBE, SYNTAX=SET_SUBSCRIBE
+		KEYWORD FILE_DIRECTORY,SYNTAX=SET_FILE_DIRECTORY
+	DEFINE SYNTAX SET_EXLIMIT
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SET_PARAM2
+			VALUE(REQUIRED,TYPE=$NUMBER)
+	DEFINE SYNTAX SET_FILE_DIRECTORY
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SET_PARAM2
+	DEFINE SYNTAX SET_NAME
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=OLDNAME, VALUE(REQUIRED)
+		PARAMETER P3, LABEL=NEWNAME, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_NODE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=NODENAME, VALUE(REQUIRED)
+		PARAMETER P3, LABEL=REMOTENAME
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_NONODE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_EXPIRE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=EXPIRATION, VALUE(TYPE=$NUMBER,REQUIRED)
+	DEFINE SYNTAX SET_GENERIC
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME, VALUE(REQUIRED)
+		QUALIFIER DAYS,VALUE(TYPE=$NUMBER,DEFAULT="7"),DEFAULT
+	DEFINE SYNTAX SET_LOGIN
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_LIBRARY 
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=LIBRARY, VALUE(REQUIRED)
+	DEFINE SYNTAX SET_FLAGS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+	DEFINE SYNTAX SET_NOFLAGS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER FOLDER, VALUE(REQUIRED)
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+	DEFINE SYNTAX SET_SUBSCRIBE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		QUALIFIER DEFAULT
+		QUALIFIER NODEFAULT, NONNEGATABLE
+		QUALIFIER PERMANENT
+		QUALIFIER NOPERMANENT, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		DISALLOW NODEFAULT AND DEFAULT
+		DISALLOW NOPERMANENT AND PERMANENT
+		DISALLOW NODEFAULT AND PERMANENT
+		DISALLOW NOT (ALL OR DEFAULT OR NODEFAULT OR PERMANENT
+			 OR NOPERMANENT)
+	DEFINE SYNTAX SET_BBOARD
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=BB_USERNAME
+		QUALIFIER EXPIRATION, VALUE(TYPE=$NUMBER)
+			LABEL=EXPIRATION, DEFAULT
+		QUALIFIER SPECIAL, NONNEGATABLE
+		QUALIFIER VMSMAIL, NONNEGATABLE
+		DISALLOW VMSMAIL AND NOT SPECIAL
+		DISALLOW VMSMAIL AND NOT BB_USERNAME
+	DEFINE SYNTAX SET_FOLDER
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SELECT_FOLDER
+		QUALIFIER MARKED, NONNEGATABLE
+		QUALIFIER UNMARKED, NONNEGATABLE
+		QUALIFIER SEEN, NONNEGATABLE
+		QUALIFIER UNSEEN, NONNEGATABLE
+		DISALLOW (MARKED AND SEEN) OR (MARKED AND UNSEEN) OR
+			 (UNMARKED AND SEEN) OR (UNMARKED AND UNSEEN)
+	DEFINE SYNTAX SET_NOACCESS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=ACCESS_ID, VALUE(LIST)
+		PARAMETER P3, LABEL=ACCESS_FOLDER
+		QUALIFIER ALL, NONNEGATABLE
+		QUALIFIER CLASS, NONNEGATABLE
+		QUALIFIER READONLY, NONNEGATABLE
+		DISALLOW NOT ALL AND NOT ACCESS_ID
+		DISALLOW ALL AND NOT READONLY
+	DEFINE SYNTAX SET_NEWS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+		QUALIFIER ALL, DEFAULT
+		QUALIFIER CLASS,VALUE(REQUIRED)
+		QUALIFIER DEFAULT, NONNEGATABLE 
+		QUALIFIER DELETE, NONNEGATABLE 
+		QUALIFIER DISABLE, NONNEGATABLE
+		QUALIFIER ENABLE, NONNEGATABLE
+		QUALIFIER EXPIRATION, NONNEGATABLE, VALUE(REQUIRED,
+				TYPE=$NUMBER)
+		QUALIFIER FULL
+		QUALIFIER LIMIT, NONNEGATABLE, VALUE(REQUIRED, 
+				TYPE=$NUMBER) 
+		QUALIFIER PRIVATE
+		QUALIFIER STORED
+  		DISALLOW (DEFAULT AND CLASS) OR (DELETE AND NOT CLASS)
+  		DISALLOW DEFAULT AND (DISABLE OR ENABLE OR PRIVATE)
+	DEFINE SYNTAX SET_ACCESS
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=ACCESS_ID, VALUE(LIST)
+		PARAMETER P3, LABEL=ACCESS_FOLDER
+		QUALIFIER READONLY, NONNEGATABLE
+		QUALIFIER CLASS, NONNEGATABLE
+		QUALIFIER ALL, NONNEGATABLE
+		DISALLOW NOT ALL AND NOT ACCESS_ID
+	DEFINE SYNTAX SET_PRIVILEGES
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=PRIVILEGES, PROMPT="Privileges"
+		VALUE (REQUIRED,LIST)
+	DEFINE SYNTAX SET_DEFAULT_EXPIRE
+		PARAMETER P1, LABEL=SET_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SET_OPTIONS)
+		PARAMETER P2, LABEL=DEFAULT_EXPIRE, VALUE(TYPE=$NUMBER,REQUIRED)
+	DEFINE VERB SHOW
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+!
+! The following are defined to allow qualifiers to be specified
+! directly after the SHOW command, i.e. SHOW/FULL FOLDER.
+! Otherwise, the CLI routines will reject the command, because it
+! first attempts to process the qualifier before process the parameter,
+! so it has no information the qualifiers are valid.
+!
+		QUALIFIER FULL, SYNTAX=SHOW_FOLDER_FULL, NONNEGATABLE
+		QUALIFIER ALL, SYNTAX=SHOW_USER
+		QUALIFIER FOLDER, VALUE, SYNTAX=SHOW_USER
+		QUALIFIER LOGIN, SYNTAX=SHOW_USER
+		QUALIFIER NOLOGIN, SYNTAX=SHOW_USER
+		QUALIFIER PRINT, SYNTAX=SHOW_KEYPAD_PRINT
+		QUALIFIER SINCE, VALUE(TYPE=$DATETIME), SYNTAX=SHOW_USER
+		QUALIFIER START, SYNTAX=SHOW_USER
+		QUALIFIER STATE, VALUE(LIST,DEFAULT=DEFAULT), NONNEGATABLE
+	DEFINE TYPE SHOW_OPTIONS
+		KEYWORD EXCLUDE
+		KEYWORD FLAGS, SYNTAX=SHOW_FLAGS
+		KEYWORD FOLDER, SYNTAX=SHOW_FOLDER
+		KEYWORD INCLUDE
+		KEYWORD KEYPAD, SYNTAX=SHOW_KEYPAD
+		KEYWORD LIBRARY, SYNTAX=SHOW_LIBRARY
+		KEYWORD NEW, SYNTAX=SHOW_FLAGS
+		KEYWORD PRIVILEGES, SYNTAX=SHOW_FLAGS
+		KEYWORD THREAD
+		KEYWORD USER, SYNTAX=SHOW_USER
+		KEYWORD VERSION
+	DEFINE SYNTAX SHOW_FLAGS
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+	DEFINE SYNTAX SHOW_KEYPAD
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+                PARAMETER P2, LABEL=SHOW_KEY
+		QUALIFIER PRINT
+		DISALLOW PRINT AND SHOW_KEY
+		QUALIFIER STATE, VALUE(LIST,DEFAULT=DEFAULT), NONNEGATABLE
+			DEFAULT
+	DEFINE SYNTAX SHOW_KEYPAD_PRINT
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		QUALIFIER PRINT,DEFAULT
+	DEFINE SYNTAX SHOW_LIBRARY
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		QUALIFIER ALL
+	DEFINE SYNTAX SHOW_FOLDER
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+	DEFINE SYNTAX SHOW_USER
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=USERNAME
+		QUALIFIER ALL
+		QUALIFIER FOLDER, VALUE
+		QUALIFIER LOGIN
+		QUALIFIER NOLOGIN
+		QUALIFIER SINCE, VALUE(TYPE=$DATETIME)
+		QUALIFIER START, VALUE
+		DISALLOW (NOLOGIN OR LOGIN OR ALL) AND USERNAME
+		DISALLOW (LOGIN AND NOLOGIN)
+		DISALLOW (LOGIN OR NOLOGIN) AND FOLDER
+	DEFINE SYNTAX SHOW_FOLDER_FULL
+		QUALIFIER FULL, DEFAULT
+		PARAMETER P1, LABEL=SHOW_PARAM1, PROMPT="What"
+			VALUE(REQUIRED, TYPE=SHOW_OPTIONS)
+		PARAMETER P2, LABEL=SHOW_FOLDER
+	DEFINE VERB SUBSCRIBE
+        DEFINE VERB SPAWN
+		PARAMETER P1, LABEL=COMMAND, VALUE(TYPE=$REST_OF_LINE)
+	DEFINE VERB UNMARK
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB UNDELETE
+		PARAMETER P1, LABEL=BULLETIN_NUMBER, VALUE(TYPE=$FILE)
+	DEFINE VERB UNSEEN
+		PARAMETER P1, LABEL=NUMBER, VALUE(TYPE=$FILE,LIST)
+	DEFINE VERB UNSUBSCRIBE
+$eod 
+$copy/log sys$input BULLETIN.CLD
+$deck
+!
+!  This file is the CLD file used to define a command to execute
+!  BULLETIN by using CDU, which adds the command  to the command table.
+!  The alternative is to define a symbol to execute BULLETIN.
+!  Either way will work, and it is up to the user's to decide which
+!  method to work.  (If you don't know which, you probably should use
+!  the default symbol method.)
+!
+
+Define Verb BULLETIN
+  Image BULL_DIR:BULLETIN
+  Parameter P1, Label = SELECT_FOLDER, value(type=$quoted_string)
+  Qualifier ALL
+  Qualifier BBOARD
+  Qualifier BULLCP
+  Qualifier CLEANUP, Value (Required)
+  Qualifier EDIT
+  Qualifier KEYPAD, Default
+  Qualifier LIBRARY, Value (Required) 
+  Qualifier LOGIN
+  Qualifier MARKED
+  Qualifier PAGE, Default
+  Qualifier PGFLQUOTA, Value (Type = $NUMBER, Required)
+  Qualifier PROMPT, Value (Default = "BULLETIN"), Default
+  Qualifier READNEW
+  Qualifier REVERSE
+  !
+  ! The following line causes a line to be outputted separating system notices.
+  ! The line consists of a line of all "-"s, i.e.:
+  !--------------------------------------------------------------------------
+  ! If you want a different character to be used, simply put in the desired one
+  ! in the following line.  If you want to disable the feature, remove the
+  ! Default at the end of the line.  (Don't remove the whole line!)
+  !
+  Qualifier SEPARATE, Value (Default = "-"), Default
+  Qualifier SEEN
+  Qualifier STARTUP
+  Qualifier STOP
+  Qualifier SYSTEM, Value (Type = $NUMBER, Default = "7")
+  Qualifier UNMARKED
+  Qualifier UNSEEN
+  Qualifier WIDTH, Value (Type = $NUMBER, Required)
+  Qualifier WSEXTENT, Value (Type = $NUMBER, Required)
+  Disallow (WSEXTENT Or PGFLQUOTA) And Not STARTUP
+$eod 
+$copy/log sys$input BULLMAIN.CLD
+$deck
+	MODULE BULLETIN_MAINCOMMANDS
+	DEFINE VERB BULLETIN
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER ALL
+		QUALIFIER BBOARD
+		QUALIFIER BULLCP
+		QUALIFIER CLEANUP, LABEL=CLEANUP, VALUE(REQUIRED)
+		QUALIFIER EDIT
+		QUALIFIER KEYPAD, DEFAULT
+		QUALIFIER LIBRARY, VALUE(REQUIRED)
+		QUALIFIER LOGIN
+		QUALIFIER MARKED
+		QUALIFIER PAGE, DEFAULT
+		QUALIFIER PGFLQUOTA, VALUE(TYPE=$NUMBER, REQUIRED)
+		QUALIFIER READNEW
+		QUALIFIER REVERSE
+!
+! The following line causes a line to be outputted separating system notices.
+! The line consists of a line of all "-"s, i.e.:
+!--------------------------------------------------------------------------
+! If you want a different character to be used, simply put in the desired one
+! in the following line.  If you want to disable the feature, remove the
+! DEFAULT at the end of the line.  (Don't remove the whole line!)
+!
+		QUALIFIER SEEN
+		QUALIFIER SEPARATE, VALUE(DEFAULT="-"), DEFAULT
+		QUALIFIER STARTUP
+		QUALIFIER STOP
+		QUALIFIER SYSTEM, VALUE(TYPE=$NUMBER, DEFAULT="7")
+		QUALIFIER UNSEEN
+		QUALIFIER UNMARKED
+		QUALIFIER WIDTH, VALUE(TYPE=$NUMBER, REQUIRED)
+		QUALIFIER WSEXTENT, VALUE(TYPE=$NUMBER, REQUIRED)
+		DISALLOW (WSEXTENT OR PGFLQUOTA) AND NOT STARTUP
+$eod 
+$copy/log sys$input BULLSTART.COM
+$deck
+$ RUN SYS$SYSTEM:INSTALL
+BULL_DIR:BULLETIN/SHAR/OPEN/HEAD/-
+PRIV=(OPER,SYSPRV,CMKRNL,WORLD,DETACH,PRMMBX,SYSNAM)
+/EXIT
+$ BULL*ETIN :== $BULL_DIR:BULLETIN
+$ BULLETIN/STARTUP
+$eod 
+$copy/log sys$input BULL_NEWSDUMMY.FOR
+$deck
+	INTEGER FUNCTION NEWS_ASSIGN()
+
+	NEWS_ASSIGN = 0
+
+	RETURN
+	END
+
+	INTEGER FUNCTION NEWS_GET_CHAN(I)
+
+	NEWS_GET_CHAN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWS_SET_CHAN(I)
+
+	RETURN
+	END
+
+	INTEGER FUNCTION NEWS_SOCKET_BULLCP(I,J,K,L)
+
+	NEWS_SOCKET_BULLCP = 0
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION NEWS_CREATE_BULLCP(I,J,K,L)
+
+	NEWS_CREATE_BULLCP = 0
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION NEWS_WRITE_PACKET_BULLCP(I,J,K,L,M,N)
+
+	NEWS_WRITE_PACKET_BULLCP = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWS_DISCONNECT
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_CONNECT
+
+	NEWS_CONNECT = .FALSE.
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_WRITE_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_WRITE_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_READ_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_READ_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_GETHOSTNAME(BUF)
+
+	CHARACTER*(*) BUF
+
+	NEWS_GETHOSTNAME = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_GETHOST()
+
+	NEWS_GETHOST = 0
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SMTP_DISCONNECT
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION SMTP_CONNECT
+
+	SMTP_CONNECT = .FALSE.
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION SMTP_WRITE_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	SMTP_WRITE_PACKET = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION SMTP_READ_PACKET(BUF)
+
+	CHARACTER*(*) BUF
+
+	SMTP_READ_PACKET = 0
+
+	RETURN
+	END
+$eod 
+$copy/log sys$input CREATE.COM
+$deck
+$ FQ = ""
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN FQ = "/SEPARATE_COMPILATION"
+$ IF F$GETSYI("VP_MASK") .NE. 0 THEN FQ = FQ + "/NOHPO"
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN0
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN1
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN2
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN3
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN4
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN5
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN6
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN7
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN8
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN9
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN10
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN11
+$ IF F$GETSYI("HW_MODEL") .LE. 1023 THEN MAC ALLMACS
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN MAC ALLMACS_AXP
+$ SET COMMAND/OBJ BULLCOM
+$ SET COMMAND/OBJ BULLMAIN
+$ CC = "CC/STAN=VAX"
+$ ON WARNING THEN GOTO DUMMY
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .NES. "" THEN GOTO MULTI
+$ IF F$TRNLNM("TWG$TCP") .EQS. "" THEN GOTO MULTI
+$ DEFINE DECC$USER_INCLUDE TWG$TCP:[NETDIST.INCLUDE],-
+                      TWG$TCP:[NETDIST.INCLUDE.SYS],-
+                      TWG$TCP:[NETDIST.INCLUDE.VMS],-
+                      TWG$TCP:[NETDIST.INCLUDE.NETINET],-
+                      TWG$TCP:[NETDIST.INCLUDE.ARPA]
+$ CC BULL_NEWS/DEFINE=(TWG=1)
+$ GOTO LINK
+$MULTI:
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .EQS. "" THEN GOTO UCX
+$ CC BULL_NEWS/DEFINE=(MULTINET=1)
+$ GOTO LINK
+$UCX:
+$ IF F$TRNLNM("UCX$DEVICE") .EQS. "" THEN GOTO CMU
+$ CC BULL_NEWS/DEFINE=(UCX=1)
+$ GOTO LINK
+$CMU:
+$ CC BULL_NEWS
+$ GOTO LINK
+$DUMMY:
+$ WRITE SYS$OUTPUT "There is no C compiler available for the NEWS software."
+$ WRITE SYS$OUTPUT "BULLETIN will be assembled without that feature."
+$ FORTRAN BULL_NEWSDUMMY
+$LINK:
+$ SET NOON
+$ IF F$SEARCH("BULL_DIR:READ_BOARD.COM") .NES. "" THEN-
+  DELETE BULL_DIR:READ_BOARD.COM;*
+$ IF F$SEARCH("BULL.OLB") .NES. "" THEN DELETE BULL.OLB;*
+$ IF F$SEARCH("BULL.OLB") .EQS. "" THEN LIBRARY/CREATE BULL
+$ LIBRARY BULL *.OBJ;
+$ DELETE *.OBJ;*
+$ @BULLETIN.LNK
+$eod 
+$copy/log sys$input INSTALL.COM
+$deck
+$ IF F$TRN("BULL_DIR") .EQS. ""
+$ THEN
+$   WRITE SYS$OUTPUT "ERROR: BULL_DIR has not been defined yet."
+$   WRITE SYS$OUTPUT "Assign BULL_DIR as a logical name or modify this"
+$   WRITE SYS$OUTPUT "command procedure to point to the appropriate directory."
+$   EXIT
+$ ENDIF
+$ COPY BULLETIN.EXE BULL_DIR:
+$ RUN SYS$SYSTEM:INSTALL
+BULL_DIR:BULLETIN/DEL
+BULL_DIR:BULLETIN/SHAR/OPEN/HEAD/-
+PRIV=(OPER,SYSPRV,CMKRNL,WORLD,DETACH,PRMMBX,SYSNAM)
+/EXIT
+$!
+$! NOTE: BULLETIN requires a separate help library. If you do not wish
+$! the library to be placed in SYS$HELP, modify the following lines and
+$! define the logical name BULL_HELP to be the help library directory, i.e.
+$!	$ DEFINE/SYSTEM BULL_HELP SYSD$:[NEWDIRECTORY]
+$! The above line should be placed in BULLSTART.COM to be executed after
+$! every system reboot.
+$!
+$ IF F$SEARCH("SYS$HELP:BULL.HLB") .NES. "" THEN LIBRARY/DELETE=*/HELP SYS$HELP:BULL
+$ IF F$SEARCH("SYS$HELP:BULL.HLB") .EQS. "" THEN LIBRARY/CREATE/HELP SYS$HELP:BULL
+$ LIBRARY/HELP SYS$HELP:BULL BULLCOMS1,BULLCOMS2
+$ LIBRARY/HELP SYS$HELP:HELPLIB BULLETIN
+$eod 
+$copy/log sys$input INSTRUCT.COM
+$deck
+$ BULLETIN
+ADD/PERMANENT/SYSTEM INSTRUCT.TXT/NOEDIT
+INFO ON HOW TO USE THE BULLETIN UTILITY.
+ADD/PERMANENT NONSYSTEM.TXT/NOEDIT
+INFO ON BEING PROMPTED TO READ NON-SYSTEM BULLETINS.
+EXIT
+$eod 
+$copy/log sys$input MAKEFILE.
+$deck
+# Makefile for BULLETIN
+ 
+Bulletin : Bulletin.Exe Bull.Hlb
+ 
+Bulletin.Exe : Bull.Olb
+   Link /NoTrace Bull.Olb/Lib /Inc=Bulletin$Main,Sys$System:Sys.Stb/Sel -
+        /NoUserlib /Exe=Bulletin.Exe,Sys$Input/Opt
+   ID="V2.3" $
+ 
+Bull.Olb : Bulletin.Obj Bulletin0.Obj Bulletin1.Obj Bulletin2.Obj  \
+           Bulletin3.Obj Bulletin4.Obj Bulletin5.Obj Bulletin6.Obj \
+           Bulletin7.Obj Bulletin8.Obj Bulletin9.Obj Bulletin10.Obj \
+           Bulletin11.Obj Bullcom.Obj Bullmain.Obj Allmacs.Obj
+   Library /Create Bull.Olb *.Obj
+   Purge /Log *.Obj,*.Exe
+ 
+Bulletin.Obj : Bulletin.For Bullfiles.Inc Bulldir.Inc Bullfolder.Inc \
+               Bulluser.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin.For
+ 
+Bulletin0.Obj : Bulletin0.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin0.For
+ 
+Bulletin1.Obj : Bulletin1.For Bulldir.Inc Bullfolder.Inc Bulluser.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin1.For
+ 
+Bulletin2.Obj : Bulletin2.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin2.For
+ 
+Bulletin3.Obj : Bulletin3.For Bulldir.Inc Bullfolder.Inc Bulluser.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin3.For
+ 
+Bulletin4.Obj : Bulletin4.For Bullfolder.Inc Bulluser.Inc Bullfiles.Inc \
+                Bulldir.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin4.For
+ 
+Bulletin5.Obj : Bulletin5.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin5.For
+ 
+Bulletin6.Obj : Bulletin6.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin6.For
+ 
+Bulletin7.Obj : Bulletin7.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin7.For
+ 
+Bulletin8.Obj : Bulletin8.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin8.For
+ 
+Bulletin9.Obj : Bulletin9.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin9.For
+ 
+Bulletin10.Obj : Bulletin10.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin10.For
+ 
+Bulletin11.Obj : Bulletin11.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin11.For
+ 
+Allmacs.Obj : Allmacs.mar
+   Macro   /NoList Allmacs.Mar
+ 
+Bullcom.Obj : Bullcom.cld
+   Set Command /Obj Bullcom.Cld
+ 
+Bullmain.Obj : Bullmain.cld
+   Set Command /Obj Bullmain.Cld
+ 
+Bull.Hlb : Bullcoms1.Hlp Bullcoms2.Hlp
+   Library /Create /Help Bull.Hlb Bullcoms1.Hlp, Bullcoms2.Hlp
+   Purge Bull.Hlb
+*.hlb :
+        lib/help/cre $*
+$eod 
+$copy/log sys$input OPTIMIZE_RMS.COM
+$deck
+$ SET NOON
+$ EXIT_STATUS = 1
+$ IF P1 .NES. "" THEN GOTO BATCH
+$!
+$GET_FILE:
+$ INQUIRE P1 "File to be optimized (^Y to quit)"
+$!
+$ FILENAME = P1
+$ SPEC = F$SEARCH(FILENAME)
+$!
+$GOT_NAME_INTERACTIVE:
+$ NAME = F$PARSE(FILENAME,,,"NAME")
+$!
+$ IF F$FILE_ATTRIBUTE(FILENAME,"ORG") .EQS. "IDX" THEN-
+  GOTO INTERACTIVE_CHECK_ADDS
+$ WRITE SYS$OUTPUT "File not indexed"
+$ GOTO GET_FILE
+$INTERACTIVE_CHECK_ADDS:
+$ INQUIRE P2 "Number of records to add after initial load"
+$ IF P2 .EQS. "" THEN P2 = 0
+$!
+$ IF P2 .GE. 0 THEN GOTO INTERACTIVE_CHECK_CONVERT
+$ WRITE SYS$OUTPUT "Added records must be >= 0 "
+$ GOTO GOT_NAME_INTERACTIVE
+$!
+$INTERACTIVE_CHECK_CONVERT:
+$ INQUIRE P3 "Turn OFF Data and Key compression? (N)"
+$ INQUIRE P4 "Turn OFF Index compression? (N)"
+$!
+$ GOTO ADD_OK
+$!
+$BATCH:
+$GOT_NAME:
+$ FILENAME = P1
+$ SPEC = F$SEARCH(FILENAME)
+$!
+$ IF SPEC .NES. "" THEN GOTO FILE_EXISTS
+$ WRITE SYS$OUTPUT "File does not exist"
+$ EXIT_STATUS = %X18292
+$ GOTO DONE
+$!
+$FILE_EXISTS:
+$ NAME = F$PARSE(FILENAME,,,"NAME")
+$ IF F$FILE_ATTRIBUTE(FILENAME,"ORG") .EQS. "IDX" THEN-
+  GOTO TYPE_OK
+$ WRITE SYS$OUTPUT "File not indexed"
+$ EXIT_STATUS = 1000024
+$ GOTO DONE
+$!
+$TYPE_OK:
+$ IF P2 .EQS. "" THEN P2 = 0
+$ IF P2 .GE. 0 THEN GOTO ADD_OK
+$!
+$ WRITE SYS$OUTPUT "Added records must be >= 0 "
+$ EXIT_STATUS = %X38060
+$ GOTO DONE
+$!
+$ADD_OK:
+$ ADD_RECORDS = P2
+$!
+$ NUMBER_OF_KEYS == 'F$FILE_ATTRIBUTE(FILENAME,"NOK")
+$ TURN_DATA_COMPRESSION_OFF = P3
+$ TURN_INDEX_COMPRESSION_OFF = "Y"
+$ FDL_NAME = F$PARSE(".FDL;0",SPEC)
+$ TEMP_FILE = "''NAME'_TEMP_TEMP.COM"
+$ OPEN/WRITE/ERROR=OPEN_ERROR OUT 'TEMP_FILE
+$ WRITE OUT "$ DEFINE/USER SYS$COMMAND SYS$INPUT"
+$ WRITE OUT "$ ANALYZE/RMS/FDL/OUT=''FDL_NAME' ''FILENAME'"
+$ WRITE OUT "$ DEFINE/USER SYS$COMMAND SYS$INPUT"
+$ WRITE OUT "$ DEFINE/USER EDF$$PLAYBACK_INPUT KLUDGE"
+$ WRITE OUT "$ EDIT/FDL/SCRIPT=OPTIMIZE/ANALYZE=''FDL_NAME' ''FDL_NAME'"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT 'ADD_RECORDS
+$ IF ADD_RECORDS .EQ. 0 THEN GOTO SKIP_NON_ZERO
+$ WRITE OUT ""
+$ WRITE OUT ""
+$SKIP_NON_ZERO:
+$ WRITE OUT ""
+$ IF TURN_INDEX_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "IC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ IF TURN_DATA_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "RC"
+$  WRITE OUT "NO"
+$  WRITE OUT "KC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ WRITE OUT "FD"
+$ WRITE OUT "Created from OPTIMIZE_RMS.COM, WITH SPACE/BUCKETSIZE for" +-
+  " ''A DD_RECORDS' ADDED RECORDS"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$LOOP:
+$ IF NUMBER_OF_KEYS .EQ. 1 THEN GOTO CLOSE_FILE
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ IF TURN_INDEX_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "IC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ IF TURN_DATA_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "KC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ WRITE OUT "FD"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ NUMBER_OF_KEYS = 'NUMBER_OF_KEYS - 1
+$ GOTO LOOP
+$!
+$CLOSE_FILE:
+$ WRITE OUT "E"
+$ CLOSE OUT
+$!
+$ @'TEMP_FILE
+$ DELETE 'TEMP_FILE;*
+$ WRITE SYS$OUTPUT ""
+$ WRITE SYS$OUTPUT "Starting CONVERT of ''FILENAME'"
+$ CONVERT /NOSORT /STAT /FDL='FDL_NAME 'FILENAME 'FILENAME
+$ WRITE SYS$OUTPUT ""
+$ GOTO DONE
+$OPEN_ERROR:
+$ WRITE SYS$OUTPUT "Unable to open ''TEMP_FILE'"
+$DONE:
+$ EXIT 'EXIT_STATUS
+$eod 
+$copy/log sys$input RESTART.COM
+$deck
+$ SET PROCESS/PRIVILEGE=ALL
+$ MCR SYSMAN
+SET ENV/CL
+SET PROF/PRIV=ALL
+DO DEASSIGN BULL_DISABLE/SYSTEM
+$ BULL/START
+$eod 
+$copy/log sys$input SETUSER.MAR
+$deck
+	.Title	SETUSER
+;
+;	Program Setuser
+;
+;	This program will change the username and UIC of the running process
+;
+;	To assemble:	$ MACRO SETUSER
+;			$ LINK SETUSER,SYS$SYSTEM:SYS.STB/SELECT
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+	$PCBDEF				;define PCB offsets
+	$JIBDEF				;define JIB offsets
+	$UAFDEF				;define user authorization file offsets
+INFAB:	$FAB	FAC=GET -		;only gets on input file
+		FNM=<SYSUAF> -		;SYSUAF may be defined as logical name
+		DNM=<SYS$SYSTEM:.DAT> -	;These are default directory & suffix
+		SHR=<PUT,GET,DEL,UPD>	;allow full sharing
+INRAB:	$RAB	FAB=INFAB -		;FAB for this RAB
+		KBF=COMMLD+8 -		;key value is typed in by user
+		KRF=0 -			;primary key
+		KSZ=12 -		;username is 12 bytes long
+		RAC=KEY -		;key access on this file
+		ROP=NLK -		;don't lock read records
+		UBF=BUFFER -		;address of buffer for I/O
+		USZ=2048		;size of buffer
+BUFFER:	.BLKB	2048			;buffer for data
+COMMLD:	.ASCID	/            /		;space for typed in username
+PROMPTD:.ASCID	/Username: /		;prompt string
+COMMLDS:.WORD	0			;space for number of bytes typed in
+FAODESC:.LONG	80
+	.LONG	FAOBUF
+FAOBUF:	.BLKB	80
+FAOLEN:	.BLKW	1
+	.BLKW	1
+FORSTR:	.ASCID	/PID:!XL from:[!OW,!OW] !AD to:[!OW,!OW] !AD/
+TT:	.ASCID	/SYS$OUTPUT/
+CHANTT:	.WORD	0			;space for terminal channel number
+IOSB:	.QUAD	0
+OLDUSER:.BLKB	12			;space for old username
+OLDUIC:	.BLKL	1			;space for old uic
+ERRORB:	JMP	ERROR			;for branch out of range
+
+JPIUSER:	.BLKB	12
+JPIUSER_LEN:	.BLKL	1
+
+	$DEFINI IT			;DEFINE ITEM LIST FOR GETJPI
+$DEF	ITL	.BLKW	1		;LENGTH OF OUTPUT BUFFER
+$DEF	ITM	.BLKW	1		;ITEM CODE (PROCESS NAME)
+$DEF	ITA	.BLKL	1		;ADDR OF OUTPUT BUFFER
+$DEF	ITAL	.BLKL	1		;ADDR OF WORD TO RECIEVE BYTES USED
+$DEF	ITEND	.BLKL	1		;ZERO LONG WORD TO END LIST
+$DEF	ITSIZE				;SIZE NEEDED FOR IT BLOCK
+	$DEFEND IT
+
+	.ENTRY	START,^M<>		;start of program
+	PUSHAW	COMMLDS			;address of word to get read byte count
+	PUSHAL	PROMPTD			;address of prompt string descriptor
+	PUSHAL	COMMLD			;address of descriptor to get command
+	CALLS	#3,G^LIB$GET_FOREIGN	;use run time library to get command
+	BLBC	R0,ERRORB		;low bit clear error
+	$OPEN	FAB=INFAB		;open file
+	BLBC	R0,ERRORB		;low bit clear error
+	$CONNECT RAB=INRAB		;connect file
+	BLBC	R0,ERRORB		;low bit clear error
+	$GET	RAB=INRAB		;read a record
+	CMPL	R0,#RMS$_RNF		;record not found?
+	BEQL	errorb			;that's all folks
+	CMPL	R0,#RMS$_NORMAL		;ok?
+	BNEQ	ERRORB			;no so quit
+
+	SUBL	#ITSIZE,SP		;GET SPACE FOR ITEM LIST
+	MOVL	SP,R2			;POINT TO IT
+	MOVW	#12,ITL(R2)		;SET UP ITEM LIST
+	MOVW	#JPI$_USERNAME,ITM(R2)
+	MOVAB	JPIUSER,ITA(R2)
+	MOVAW	JPIUSER_LEN,ITAL(R2)
+	CLRL	ITEND(R2)
+	$GETJPI_S	ITMLST=(R2)	;GET PROCESS NAME
+	ADDL	#ITSIZE,SP		;RESTORE STACK POINTER
+
+	MOVL	INRAB+RAB$L_RBF,R7	;put address of read record in R7
+	MOVL	UAF$L_UIC(R7),R8	;R8 has UIC we want
+	$CMKRNL_S TWEAK			;change mode to kernel to tweak UIC
+					;and username
+	BLBC	R0,ERROR		;low bit clear error
+	ADDL3	#UAF$S_USERNAME,R7,R8
+	ADDL3	#UAF$T_USERNAME,R7,R9
+	$FAO_S	CTRSTR=FORSTR,-		;format string
+		OUTBUF=FAODESC,-	;char descript for formatted output
+		OUTLEN=FAOLEN,-		;long word to hold length of output
+		P1=R9,-			;PID
+		P2=OLDUIC+2,-		;old UIC, group number
+		P3=OLDUIC,-		;old UIC, member number
+		P4=#12,-		;usernames are 12 bytes
+		P5=#OLDUSER,-		;address of old username
+		P6=UAF$L_UIC+2(R7),-	;UIC, group number
+		P7=UAF$L_UIC(R7),-	;UIC, member number
+		P8=R8,-			;usernames are 12 bytes
+		P9=R9			;address of username
+	BLBC	R0,ERROR		;low bit clear error
+	MOVL	FAOLEN,FAODESC
+	PUSHAL	FAODESC			;address of descriptor to get command
+	CALLS	#1,G^LIB$PUT_OUTPUT	;use run time library to get command
+	BLBC	R0,ERROR		;low bit clear error
+EXIT:
+	$CLOSE	FAB=INFAB -		;close file
+		ERR=ERROR
+ERROR:	$EXIT_S	R0			;exit with error if any
+	.ENTRY	TWEAK,^M<>		;beginning of kernel mode code
+	MOVL	@#CTL$GL_PCB,R11	;put address of our PCB in R11
+	MOVL	PCB$L_PID(R11),R9	;save PID
+	MOVL	PCB$L_UIC(R11),OLDUIC	;save old UIC
+	MOVL	R8,PCB$L_UIC(R11)	;change our UIC
+	MOVL	PCB$L_JIB(R11),R10	;put address of Job Info Block in R10
+					;MOVC blats R0-R5
+	MOVC3	#12,JIB$T_USERNAME(R10),OLDUSER ;save old username
+	CMPC3	JPIUSER_LEN,JPIUSER,OLDUSER
+	BEQL	GOOD
+	CLRL	R0
+	RET	
+GOOD:	MOVC3	#12,UAF$T_USERNAME(R7),JIB$T_USERNAME(R10) ;change username JIB
+	MOVC3	#12,UAF$T_USERNAME(R7),CTL$T_USERNAME ;change username in P1
+EEXIT:	MOVL	#SS$_NORMAL,R0		;set normal exit status
+	RET				;end of exec mode code
+	.END	START			;end of program
+$eod 
+$copy/log sys$input UPGRADE.COM
+$deck
+$!
+$!  Normally, new versions of BULLETIN don't require any special
+$!  installation except to link and install the new executable (and
+$!  possibly relink PMDF or MX interfaces if any changes affect them).
+$!  However, when there is a change to the data file format, you should run
+$!  the following procedure.         
+$!
+$!  This is a sample upgrade procedure.  You will have to modify references
+$!  to the directory where the new executables are stored, which are marked
+$!  with ***. You will also have to change the references to the procedures
+$!  that link either PMDF or MX.  These procedures usually replace the old
+$!  executable, but that should not be done until BULLETIN has been disabled
+$!  (by defining the logical name BULL_DISABLE).  If you run this procedure
+$!  with a parameter (i.e. @UPGRADE LINK), it will call those linking
+$!  procedures. Alternatively, you could define BULL_DISABLE and run those
+$!  procedures manually.  Or, you could change them so they don't replace the
+$!  old procedures and run them manually, and simply have this procedure
+$!  replace them.  Whatever you find more convenient.
+$!  
+$!  This procedure should be run on all stand alone nodes or boot nodes of
+$!  clusters on which bulletin is installed. After running upgrade.com, run
+$!  restart.com to restart bulletin.  If you don't make use of remote
+$!  folders, you can run restart.com immediately after upgrade.com rather
+$!  than waiting to install the new version on all nodes.  Otherwise, you
+$!  should try to run this procedure simultaneously on all clusters and then
+$!  wait until it finishes on all nodes before running restart.com. 
+$!  Otherwise, remote folder access attempts will fail.                 
+$!  
+$ SET PROCESS/PRIVILEGE=ALL
+$ COPY ALCVAX::USER1:[MRL.BULLETIN]BULLETIN.EXE BULL_DIR:              ! *** 
+$ COPY ALCVAX::USER1:[MRL.BULLETIN]BULL.HLB SITE$ROOT:[SYSHLP]         ! *** 
+$ PMDF = F$TRNLNM("PMDF_ROOT")
+$ MX = F$TRNLNM("MX_EXE")
+$ BULL/STOP
+$ IF PMDF .NES. "" THEN PMDF = F$SEARCH("PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE")
+$ IF PMDF .NES. "" THEN DELETE/NOCONFIRM PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE;*
+$ IF MX .NES. "" THEN MX = F$SEARCH("MX_EXE:MX_BULL.EXE")
+$ IF MX .NES. "" THEN DELETE/NOCONFIRM MX_EXE:MX_BULL.EXE;*
+$ MCR SYSMAN
+SET ENV/CL
+SET PROF/PRIV=ALL
+DO DEFINE BULL_DISABLE/SYSTEM "DISABLE"
+DO MCR INSTALL BULL_DIR:BULLETIN/REPLACE
+$ IF P1 .NES. "" .AND. PMDF .NES. "" THEN @USER1:[MRL.BULLETIN]LINK_PMDF ! ***
+$ IF P1 .NES. "" .AND. MX .NES. "" THEN @USER1:[MRL.BULLETIN]LINK_MX	 ! ***
+$ DEFINE BULL_DISABLE "ENABLE"		! Enable it just for this process.
+$ BULLETIN
+$ IF F$TRNLNM("BULL_NEWS_SERVER") .NES. "" THEN BULLETIN MISC.TEST
+$ IF PMDF .NES. "" THEN-
+   COPY ALCVAX::PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE PMDF_ROOT:[EXE]	! ***
+$ IF MX .NES. "" THEN-
+   COPY ALCVAX::MX_EXE:MX_BULL.EXE MX_EXE:                 		! ***
+$ DEASSIGN BULL_DISABLE
+$eod 
diff --git a/decus/vmslt98a/bulletin/bulletin.cld b/decus/vmslt98a/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..95c9f312f53857ea7afa22a5ab608ef937c0a222
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin.cld
@@ -0,0 +1,44 @@
+!
+!  This file is the CLD file used to define a command to execute
+!  BULLETIN by using CDU, which adds the command  to the command table.
+!  The alternative is to define a symbol to execute BULLETIN.
+!  Either way will work, and it is up to the user's to decide which
+!  method to work.  (If you don't know which, you probably should use
+!  the default symbol method.)
+!
+
+Define Verb BULLETIN
+  Image BULL_DIR:BULLETIN
+  Parameter P1, Label = SELECT_FOLDER, value(type=$quoted_string)
+  Qualifier ALL
+  Qualifier BBOARD
+  Qualifier BULLCP
+  Qualifier CLEANUP, Value (Required)
+  Qualifier EDIT
+  Qualifier KEYPAD, Default
+  Qualifier LIBRARY, Value (Required) 
+  Qualifier LOGIN
+  Qualifier MARKED
+  Qualifier PAGE, Default
+  Qualifier PGFLQUOTA, Value (Type = $NUMBER, Required)
+  Qualifier PROMPT, Value (Default = "BULLETIN"), Default
+  Qualifier READNEW
+  Qualifier REVERSE
+  !
+  ! The following line causes a line to be outputted separating system notices.
+  ! The line consists of a line of all "-"s, i.e.:
+  !--------------------------------------------------------------------------
+  ! If you want a different character to be used, simply put in the desired one
+  ! in the following line.  If you want to disable the feature, remove the
+  ! Default at the end of the line.  (Don't remove the whole line!)
+  !
+  Qualifier SEPARATE, Value (Default = "-"), Default
+  Qualifier SEEN
+  Qualifier STARTUP
+  Qualifier STOP
+  Qualifier SYSTEM, Value (Type = $NUMBER, Default = "7")
+  Qualifier UNMARKED
+  Qualifier UNSEEN
+  Qualifier WIDTH, Value (Type = $NUMBER, Required)
+  Qualifier WSEXTENT, Value (Type = $NUMBER, Required)
+  Disallow (WSEXTENT Or PGFLQUOTA) And Not STARTUP
diff --git a/decus/vmslt98a/bulletin/bulletin.com b/decus/vmslt98a/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..84cf2941ed510ffb1b6f02800a42163619fca602
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin.com
@@ -0,0 +1,2 @@
+$ DEFINE SYS$INPUT SYS$NET
+$ BULLETIN
diff --git a/decus/vmslt98a/bulletin/bulletin.for b/decus/vmslt98a/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..27b5a5991317a4ec1680c1411838acc449a30a09
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin.for
@@ -0,0 +1,2129 @@
+C
+C  BULLETIN.FOR, Version 2/27/98
+C  Purpose: Bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	EXTERNAL BULLETIN_SUBCOMMANDS,LIB$GET_INPUT
+	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
+	CHARACTER*44 PROMPT
+
+	COMMON /NEXT_COMMAND/ NEXT_COMMAND
+	CHARACTER NEXT_COMMAND*64
+	DATA NEXT_COMMAND/' '/
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/
+
+	COMMON /DCL/ DCL_CMD,DCL_COMMAND
+	CHARACTER DCL_CMD*132
+
+	CALL INIT_BULLETIN(.TRUE.)
+
+C
+C  The MAIN loop for processing bulletin commands.
+C
+
+	LPROMPT = TRIM(COMMAND_PROMPT)
+	PROMPT = CHAR(10)//COMMAND_PROMPT(:LPROMPT)//' '
+	LPROMPT = LPROMPT + 2
+
+	DO WHILE (LPROMPT.GT.0)
+
+	   IF (.NOT.DCL_COMMAND) THEN
+	      CALL COMMAND_INPUT(IER)
+	   ELSE
+	      IF (INDEX(DCL_CMD,';').GT.0) THEN
+	         INCMD = DCL_CMD(:INDEX(DCL_CMD,';')-1)
+	         DCL_COMMAND = DCL_CMD(INDEX(DCL_CMD,';'):).NE.';'
+	         DCL_CMD = DCL_CMD(INDEX(DCL_CMD,';')+1:)
+	      ELSE
+	         INCMD = DCL_CMD
+	         DCL_CMD = ' '
+	      END IF
+ 	      IER = TRIM(INCMD)
+	   END IF
+
+	   IF (IER.EQ.-2) THEN
+	      IER = RMS$_EOF
+	   ELSE IF (IER.LE.0) THEN
+	      IER = %LOC(CLI$_NOCOMD)
+	   ELSE
+	      DO WHILE (IER.GT.0.AND.INCMD(:1).EQ.' ')
+		 INCMD = INCMD(2:IER)
+		 IER = IER - 1
+	      END DO
+	      IF (IER.GT.0.AND.INCMD(:1).GE.'0'.AND.INCMD(:1).LE.'9') THEN
+		 INCMD = 'READ '//INCMD
+	      END IF
+	      IF (IER.GT.0) THEN 
+		  IF (INDEX(INCMD(:IER),' ').EQ.0.AND.
+     &		      INDEX(INCMD,'/').EQ.0.AND.
+     &		      INDEX(INCMD,'.').GT.0) INCMD = 'SELECT '//INCMD
+	      END IF
+	      IER=CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS,LIB$GET_INPUT)
+	   END IF
+
+	   IF (IER.EQ.RMS$_EOF) THEN
+	      CALL EXIT			! If no command, exit
+	   ELSE IF (IER.EQ.%LOC(CLI$_NOCOMD)) THEN  ! If just RETURN entered
+	      INCMD = ' '		! Make sure there is none
+	      LEN_P = 0			! Indicate no parameter in command
+	      IF (DIR_COUNT.GT.0) THEN		! If still more dir entries
+		 CALL DIRECTORY(DIR_COUNT)	! continue outputting them
+	      ELSE IF (INDEX_COUNT.GT.0) THEN
+	         CALL FULL_DIR
+	      ELSE IF (FOLDER_COUNT.GT.0) THEN	! If more folder entries
+		 CALL DIRECTORY_FOLDERS(FOLDER_COUNT) ! continue outputting them
+	      ELSE IF (READ_COUNT.NE.0) THEN 
+		 CALL READ_MSG(READ_COUNT,BULL_POINT+1)
+	         DIR_COUNT = 0
+	         FOLDER_COUNT = 0
+	         INDEX_COUNT = 0
+	      ELSE IF (NEXT_COMMAND.NE.' ') THEN
+		 INCMD = NEXT_COMMAND
+	         IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS,LIB$GET_INPUT)
+		 CALL DO_COMMAND(INCMD)
+	      ELSE				! Else try to read next bulletin
+		 CALL READ_MSG(READ_COUNT,BULL_POINT+1)  ! or finish old one
+	         DIR_COUNT = 0
+	         FOLDER_COUNT = 0
+	         INDEX_COUNT = 0
+	      END IF
+	      GO TO 100				! Loop to read new command
+	   ELSE IF (.NOT.IER) THEN		! If command has error
+	      GO TO 100				! ask for new command
+	   END IF
+
+	   CALL DO_COMMAND(INCMD)
+
+100	   CONTINUE
+
+	   IF (DCL_COMMAND.AND.TRIM(DCL_CMD).EQ.0) CALL EXIT
+
+	END DO
+
+1010	FORMAT(Q,A)
+
+	END
+
+
+
+
+	SUBROUTINE DO_COMMAND(INCMD)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING /.FALSE./
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /NEXT_COMMAND/ NEXT_COMMAND
+	CHARACTER NEXT_COMMAND*64
+
+	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER HELP_DIRECTORY*64,SAVE_FOLDER*44
+
+	CHARACTER*(*) INCMD
+
+	NEXT_COMMAND = ' '
+
+        IER = MINGT0(INDEX(INCMD(:TRIM(INCMD)),' '),INDEX(INCMD,'/'))
+	IF (IER.GT.0) INCMD = '    '//INCMD(IER:)	! Save qualifiers
+	CALL CLI$GET_VALUE('$VERB',INCMD(:4))		! Get user's command.
+
+	IF (HLEN.EQ.0) THEN
+	   IER = LIB$SYS_TRNLOG('BULL_HELP',HLEN,HELP_DIRECTORY)
+	   IF (IER.NE.1) THEN
+	      HELP_DIRECTORY = 'SYS$HELP:'
+	      HLEN = 9
+	   ELSE IF (HELP_DIRECTORY(HLEN:HLEN).NE.':'.AND.
+     &	   	 HELP_DIRECTORY(HLEN:HLEN).NE.']') THEN
+	      HELP_DIRECTORY = HELP_DIRECTORY(:HLEN)//':'
+	      HLEN = HLEN + 1
+	   END IF
+	END IF
+
+	IF (INCMD(:4).EQ.'BACK'.AND.DIR_COUNT.NE.0) THEN
+	   DIR_COUNT = -1
+	   CALL DIRECTORY(DIR_COUNT)
+	   INCMD = ' '
+C	ELSE IF (INCMD(:4).EQ.'BACK'.AND.FOLDER_COUNT.NE.0) THEN
+C	      FOLDER_COUNT = -1
+C	      CALL DIRECTORY_FOLDERS(FOLDER_COUNT)
+C	      INCMD = ' '
+	ELSE
+	   DIR_COUNT = 0			! Reinit display pointers
+	   READ_COUNT = 0
+	   FOLDER_COUNT = 0
+	   INDEX_COUNT = 0
+	END IF
+
+	IF_ADD = INCMD(:3).EQ.'ADD'
+	IF (IF_ADD) IF_ADD = .NOT.CLI$PRESENT('SELECT_FOLDER')
+	IF (READ_ONLY.AND.(IF_ADD.OR.INCMD(:3).EQ.'DEL'.OR.
+     &	    INCMD(:4).EQ.'POST'.OR.
+     &	    INCMD(:3).EQ.'CHA'.OR.INCMD(:3).EQ.'REP')) THEN
+	   					! FOLDER can only be read?
+	   WRITE (6,'('' ERROR: Access to folder limited to reading.'')')
+	ELSE IF (INCMD(:3).EQ.'ADD') THEN	! ADD?
+	   IF (REMOTE_SET.GE.3) THEN
+	      IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+		 WRITE (6,'('' ERROR: /FOLDER not valid when posting'',
+     &			    '' a message to a news group.'')')
+	      ELSE
+		 INCMD = 'POST '//INCMD(4:)
+		 IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+		 CALL RESPOND
+	      END IF
+	   ELSE
+	      CALL ADD
+	   END IF
+	ELSE IF (INCMD(:3).EQ.'ATT') THEN	! ATTACH?
+	   CALL ATTACH
+	ELSE IF (INCMD(:4).EQ.'BACK') THEN	! BACK?
+	   IF (BULL_POINT.LE.1) THEN
+	      WRITE(6,'('' ERROR: There are no more preceding messages.'')')
+	   ELSE
+	      CALL READ_MSG(READ_COUNT,BULL_POINT-1)  ! Try to read previous
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'CHAN') THEN		! CHANGE?
+	   CALL REPLACE				! Replace old bulletin
+	ELSE IF (INCMD(:4).EQ.'COPY') THEN		! COPY?
+	   CALL MOVE(.FALSE.)
+	ELSE IF (INCMD(:4).EQ.'CREA') THEN		! CREATE?
+	   CALL CREATE_FOLDER			! Go create the folder
+	ELSE IF (INCMD(:4).EQ.'CURR') THEN		! CURRENT?
+	   READ_COUNT = -1		! Reread current message from beginning.
+	   CALL READ_MSG(READ_COUNT,BULL_POINT)
+	ELSE IF (INCMD(:4).EQ.'DELE') THEN 	! DELETE?
+	   CALL DELETE_MSG			! Go delete bulletin
+	ELSE IF (INCMD(:4).EQ.'DIRE') THEN		! DIRECTORY?
+	   IF (CLI$PRESENT('FOLDER').AND.CLI$PRESENT('NEWS')) THEN
+	      WRITE (6,'('' ERROR: /NEWS and /FOLDER cannot be ''
+     &		         ''specified at the same time.'')')
+	   ELSE IF (CLI$PRESENT('FOLDER').OR.		! /FOLDER specified?
+     &	       CLI$PRESENT('NEWS')) THEN		! or /NEWS?
+	      CALL DIRECTORY_FOLDERS(FOLDER_COUNT)	! Show all folders
+	   ELSE IF (CLI$PRESENT('SELECT_FOLDER')) THEN! Folder specified?
+	      CALL SELECT_FOLDER(.TRUE.,IER)		! Try to select folder
+	      IF (IER) THEN				! If successful
+		 CALL DIRECTORY(DIR_COUNT)		! Show messages
+	      END IF
+	   ELSE
+	      CALL DIRECTORY(DIR_COUNT)		! Show messages
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'FILE'.OR.
+     &		 INCMD(:4).EQ.'EXTR') THEN		! FILE?
+	   CALL FILE(0,.TRUE.,.FALSE.)			! Copy bulletin to file
+	ELSE IF (INCMD(:4).EQ.'EXCL') THEN		! EXCLUDE?
+	   CALL INCLUDE(.TRUE.)
+	ELSE IF (INCMD(:1).EQ.'E'.OR.
+     &		 INCMD(:4).EQ.'QUIT') THEN		! EXIT?
+	   CALL EXIT				! Exit from program
+	ELSE IF (INCMD(:4).EQ.'FIRS') THEN		! FIRST?
+	   READ_COUNT = -1
+	   BULL_READ = 1
+	   CALL READ_MSG(READ_COUNT,BULL_READ)
+	ELSE IF (INCMD(:4).EQ.'HELP') THEN		! HELP?
+	   CALL HELP(HELP_DIRECTORY(:HLEN)//'BULL.HLB')	! Get help
+	ELSE IF (INCMD(:3).EQ.'IND') THEN		! INDEX?
+	   INDEX_COUNT = 1
+	   CALL FULL_DIR
+	ELSE IF (INCMD(:4).EQ.'INCL'.OR.		! INCLUDE?
+     &	         INCMD(:4).EQ.'THRE') THEN		! THREAD?
+	   CALL INCLUDE(.FALSE.)
+	ELSE IF (INCMD(:4).EQ.'LAST') THEN		! LAST?
+	   READ_COUNT = -1
+	   BULL_READ = 9999999
+	   CALL READ_MSG(READ_COUNT,BULL_READ)
+	ELSE IF (INCMD(:4).EQ.'MARK') THEN		! MARK?
+	   CALL TAG(.TRUE.,1)
+	ELSE IF (INCMD(:4).EQ.'MAIL'.OR.
+     &		 INCMD(:4).EQ.'FORW') THEN		! MAIL?
+	   CALL MAIL
+	ELSE IF (INCMD(:3).EQ.'MOD') THEN		! MODIFY?
+	   CALL MODIFY_FOLDER
+	ELSE IF (INCMD(:4).EQ.'MOVE') THEN		! MOVE?
+	   CALL MOVE(.TRUE.)
+	ELSE IF (INCMD(:4).EQ.'NEWS') THEN		! NEWS
+	   CALL DIRECTORY_FOLDERS(FOLDER_COUNT)	! Show new folders
+	ELSE IF (INCMD(:4).EQ.'NEXT'.OR.INCMD(:1).EQ.'N') THEN    ! NEXT?
+	   CALL READ_MSG(READ_COUNT,BULL_POINT+1)	! Read next bulletin
+	ELSE IF (INCMD(:4).EQ.'POST') THEN		! POST?
+	   IF (BTEST(FOLDER_FLAG,11)) THEN
+	      INCMD = 'ADD '//INCMD(5:)
+	      IER=CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL ADD
+	   ELSE
+	      CALL RESPOND
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'PRIN') THEN		! PRINT?
+	   CALL PRINT(0,.TRUE.)			! Printout bulletin
+	ELSE IF (INCMD(:4).EQ.'READ') THEN		! READ?
+	   IF (CLI$PRESENT('THREADS')) NEXT_COMMAND = 'READ/THREADS'
+	   IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN		! Bulletin specified?
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) BULL_READ	! Yes
+	      READ_COUNT = -1
+	      CALL READ_MSG(READ_COUNT,BULL_READ)
+	   ELSE
+	      CALL READ_MSG(READ_COUNT,BULL_POINT+1)
+	   END IF
+	ELSE IF (INCMD(:3).EQ.'REM') THEN		! REMOVE?
+	   CALL REMOVE_FOLDER
+	ELSE IF (INCMD(:3).EQ.'REP') THEN		! REPLY?
+	   IF (.NOT.BTEST(FOLDER_FLAG,11).AND.(REMOTE_SET.GE.3.OR.
+     &	      INDEX(FOLDER_DESCRIP,'<').GT.0)) THEN
+	      CALL RESPOND
+	   ELSE
+	      CALL REPLY
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'RESP') THEN		! RESPOND?
+	   CALL RESPOND
+	ELSE IF (INCMD(:4).EQ.'RESE') THEN		! RESET?
+	   CALL RESET
+	ELSE IF (INCMD(:3).EQ.'SEA') THEN		! SEARCH?
+	   NEXT_COMMAND = 'SEARCH'
+	   CALL SEARCH(READ_COUNT)
+	ELSE IF (INCMD(:3).EQ.'SEE') THEN		! SEEN?
+	   CALL TAG(.TRUE.,2)
+	ELSE IF (INCMD(:3).EQ.'SEL') THEN		! SELECT?
+	   CALL SELECT_FOLDER(.TRUE.,IER)
+	ELSE IF (INCMD(:3).EQ.'SET') THEN		! SET?
+	   CALL CLI$GET_VALUE('SET_PARAM1',BULL_PARAMETER)
+	   IF (BULL_PARAMETER(:2).EQ.'FO') THEN		! SET FOLDER?
+	      CALL SELECT_FOLDER(.TRUE.,IER)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'FI') THEN	! SET FILE_DIRECTORY?
+	      CALL SET_CUSTOM('file_directory')
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'PRI') THEN		! SET PRIVS?
+	      CALL SET_PRIV
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'PA') THEN		! SET PAGE?
+	      PAGING = .TRUE.
+	      WRITE (6,'('' PAGE has been set.'')')
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'K') THEN		! SET KEYPAD?
+	      CALL SET_KEYPAD
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOK') THEN		! SET NOKEYPAD?
+	      CALL SET_NOKEYPAD
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPA') THEN	! SET NOPAGE?
+	      PAGING = .FALSE.
+	      WRITE (6,'('' NOPAGE has been set.'')')
+	   ELSE IF (FOLDER_NUMBER.EQ.-1.AND.REMOTE_SET.EQ.1) THEN
+	      WRITE (6,'('' ERROR: Invalid command for remote folder.'')')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'SY') THEN		! SET SYSTEM?
+	      CALL SET_SYSTEM(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOSY') THEN	! SET NOSYSTEM?
+	      CALL SET_SYSTEM(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'BB') THEN		! SET BBOARD?
+	      CALL SET_BBOARD(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOBB') THEN	! SET NOBBOARD?
+	      CALL SET_BBOARD(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'DU') THEN		! SET DUMP?
+	      CALL SET_FOLDER_FLAG(.TRUE.,1,'DUMP')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODU') THEN	! SET NODUMP?
+	      CALL SET_FOLDER_FLAG(.FALSE.,1,'DUMP')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'ST') THEN		! SET STRIP?
+	      CALL SET_FOLDER_FLAG(.TRUE.,4,'STRIP')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOST') THEN	! SET NOSTRIP?
+	      CALL SET_FOLDER_FLAG(.FALSE.,4,'STRIP')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'DI') THEN		! SET DIGEST?
+	      CALL SET_FOLDER_FLAG(.TRUE.,5,'DIGEST')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODI') THEN	! SET NODIGEST?
+	      CALL SET_FOLDER_FLAG(.FALSE.,5,'DIGEST')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'AL') THEN		! SET ALWAYS?
+	      CALL SET_FOLDER_FLAG(.TRUE.,7,'ALWAYS')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAL') THEN	! SET NOALWAYS?
+	      CALL SET_FOLDER_FLAG(.FALSE.,7,'ALWAYS')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'AN') THEN	     ! SET ANONYMOUS?
+	      CALL SET_FOLDER_FLAG(.TRUE.,14,'ANONYMOUS')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAN') THEN     ! SET NOANONYMOUS?
+	      CALL SET_FOLDER_FLAG(.FALSE.,14,'ANONYMOUS')
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'COM') THEN	    ! SET COMPRESS?
+	      CALL SET_FOLDER_FLAG(.TRUE.,12,'COMPRESS')
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOCOM') THEN   ! SET NOCOMPRESS?
+	      CALL SET_FOLDER_FLAG(.FALSE.,12,'COMPRESS')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'PO') THEN	    ! SET POST_ONLY?
+	      CALL SET_FOLDER_FLAG(.TRUE.,10,'POST_ONLY')
+	      IF (BTEST(FOLDER_FLAG,11)) THEN
+		 CALL SET_FOLDER_FLAG(.FALSE.,11,'ADD_ONLY')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPO') THEN    ! SET NOPOST_ONLY?
+	      CALL SET_FOLDER_FLAG(.FALSE.,10,'POST_ONLY')
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'AD') THEN	    ! SET ADD_ONLY?
+	      CALL SET_FOLDER_FLAG(.TRUE.,11,'ADD_ONLY')
+	      IF (BTEST(FOLDER_FLAG,10)) THEN
+		 CALL SET_FOLDER_FLAG(.FALSE.,10,'POST_ONLY')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAD') THEN    ! SET NOADD_ONLY?
+	      CALL SET_FOLDER_FLAG(.FALSE.,11,'ADD_ONLY')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOTI') THEN	! SET NOTIFY?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(1,-1,-1)
+	      ELSE
+		 CALL SET_USER_FLAG(1,-1,-1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXP') THEN		! SET EXPIRE?
+	      IER = CLI$GET_VALUE('EXPIRATION',BULL_PARAMETER,LEN_P)
+	      IF (LEN_P.LE.3) THEN
+		 READ (BULL_PARAMETER,'(I<LEN_P>)') LIMIT
+		 CALL SET_FOLDER_EXPIRE_LIMIT(LIMIT)
+	      ELSE
+		 WRITE (6,'('' ERROR: Invalid expiration specified.'')')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODE') THEN	! SET NODE?
+	      CALL SET_NODE(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:6).EQ.'NONODE') THEN	! SET NONODE?
+	      CALL SET_NODE(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOEXP') THEN	! SET NOEXPIRE?
+	      CALL SET_FOLDER_EXPIRE_LIMIT(0)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NONOT') THEN	! SET NONOTIFY?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(0,-1,-1)
+	      ELSE
+		 CALL SET_USER_FLAG(0,-1,-1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'SH') THEN		! SET SHOWNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,1)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOS') THEN	! SET NOSHOWNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'R') THEN		! SET READNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,1,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,1,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOR') THEN	! SET NOREADNEW?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'BR') THEN		! SET BRIEF?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,1,1)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,1,1)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOBR') THEN	! SET NOBRIEF?
+	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
+     &		  CLI$PRESENT('NODEFAULT').OR.
+     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
+     &		  THEN
+		 CALL SET_FOLDER_DEFAULT(-1,0,0)
+	      ELSE
+		 CALL SET_USER_FLAG(-1,0,0)
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'SU') THEN	! SET SUBSCRIBE?
+	      IF (REMOTE_SET.GE.3) THEN
+		 D1 = 0
+		 D2 = 0
+		 D3 = 0
+		 CALL SET_FOLDER_DEFAULT(D1,D2,D3)
+	      ELSE
+		 WRITE (6,'('' ERROR: Command invalid for folder.'')')
+	      END IF
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'A') THEN	! SET ACCESS?
+	      CALL SET_ACCESS(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOA') THEN	! SET NOACCESS?
+	      CALL SET_ACCESS(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'C') THEN	! SET CONTINUOUS_BRIEF
+	      CALL SET_BRIEF_CONTINUOUS(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOC') THEN	! SET NOCONTINUOUS_BRIEF
+	      CALL SET_BRIEF_CONTINUOUS(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'GEN') THEN	! SET GENERIC?
+	      CALL SET_GENERIC(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOGEN') THEN	! SET NOGENERIC?
+	      CALL SET_GENERIC(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'LIB') THEN	! SET LIBRARY?
+	      CALL SET_LIBRARY
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'LOG') THEN		! SET LOGIN?
+	      CALL SET_LOGIN(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOLOG') THEN	! SET NOLOGIN?
+	      CALL SET_LOGIN(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'PRO') THEN	 ! SET PROMPT_EXPIRE?
+	      CALL SET_FOLDER_FLAG(.FALSE.,3,'PROMPT_EXPIRE')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPR') THEN ! SET NOPROMPT_EXPIRE?
+	      CALL SET_FOLDER_FLAG(.TRUE.,3,'PROMPT_EXPIRE')
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'DEF') THEN	! SET DEFAULT_EXPIRE?
+	      CALL SET_DEFAULT_EXPIRE
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'NE') THEN	! SET NEWS?
+	      CALL SET_NEWS
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXC') THEN	! SET EXCLUDE?
+	      BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,4)
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOEXC') THEN ! SET NOEXCLUDE?
+	      BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,4)
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXL') THEN	! SET EXLIMIT?
+	      CALL SET_CUSTOM('exclude_limit')
+	   ELSE IF (BULL_PARAMETER(:4).EQ.'NAME') THEN  ! SET NAME?
+	      CALL SET_NEWNAME
+	   ELSE IF (BULL_PARAMETER(:3).EQ.'GAT') THEN	    ! SET GATEWAY?
+	      CALL SET_FOLDER_FLAG(.TRUE.,15,'GATEWAY')
+	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOGAT') THEN   ! SET NOGATEWAY?
+	      CALL SET_FOLDER_FLAG(.FALSE.,15,'GATEWAY')
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'SHOW') THEN		! SHOW?
+	   CALL CLI$GET_VALUE('SHOW_PARAM1',BULL_PARAMETER,LEN_P)
+	   IF (BULL_PARAMETER(:2).EQ.'EX') THEN		! SHOW EXCLUDE?
+	      CALL SHOW_EXCLUDE(0)
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'FL') THEN	! SHOW FLAGS?
+	      CALL SHOW_FLAGS
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'FO') THEN	! SHOW FOLDER?
+	      CALL SHOW_FOLDER
+	   ELSE IF (BULL_PARAMETER(:2).EQ.'IN'.OR.
+     &		    BULL_PARAMETER(:2).EQ.'TH') THEN	! SHOW INCLUDE?
+	      CALL SHOW_EXCLUDE(1)
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'K') THEN	! SHOW KEYPAD
+	      CALL SHOW_KEYPAD(HELP_DIRECTORY(:HLEN)//'BULL.HLB')
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'L') THEN	! SHOW LIBRARY
+	      CALL SHOW_LIBRARY
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'N') THEN	! SHOW NEW?
+	      SAVE_FOLDER_NUMBER = FOLDER_NUMBER
+	      SAVE_FOLDER = FOLDER
+	      CALL NEW_MESSAGE_NOTIFICATION
+	      FOLDER1 = SAVE_FOLDER
+	      FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'P') THEN	! SHOW PRIVILEGES?
+	      CALL SHOW_PRIV
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'U') THEN	! SHOW USER?
+	      CALL SHOW_USER
+	   ELSE IF (BULL_PARAMETER(:1).EQ.'V') THEN	! SHOW VERSION?
+	      CALL SHOW_VERSION
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'SPAW') THEN           ! SPAWN command?
+	   CALL SPAWN_PROCESS
+	ELSE IF (INCMD(:3).EQ.'SUB') THEN            ! SUBSCRIBE command?
+	   CALL SUBSCRIBE
+	ELSE IF (INCMD(:4).EQ.'UNDE') THEN		! UNDELETE?
+	   CALL UNDELETE
+	ELSE IF (INCMD(:3).EQ.'UNM') THEN		! UNMARK?
+	   CALL TAG(.FALSE.,1)
+	ELSE IF (INCMD(:4).EQ.'UNSE') THEN		! UNSEEN?
+	   CALL TAG(.FALSE.,2)
+	ELSE IF (INCMD(:4).EQ.'UNSU') THEN           ! UNSUBSCRIBE command?
+	   CALL UNSUBSCRIBE
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE COMMAND_INPUT(IER)
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
+	CHARACTER*44 PROMPT
+
+	CALL GET_INPUT_PROMPT(INCMD,IER,PROMPT(:LPROMPT))
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE ADD
+C
+C  SUBROUTINE ADD
+C
+C  FUNCTION: Adds bulletin to bulletin file.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /INDESCRIP/ INDESCRIP
+	CHARACTER*(INPUT_LENGTH) INDESCRIP
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER INEXDATE*12,INEXTIME*12,INDENT*4
+
+	CHARACTER INLINE*80,OLD_FOLDER*44,LOCAL_NODE*8
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED,BULLETIN_SUBCOMMANDS
+
+	EDITIT = (CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.
+     &           (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))
+
+	IF (CLI$PRESENT('EXTRACT').AND..NOT.EDITIT) THEN
+	   WRITE (6,'('' ERROR: Cannot extract text without /EDIT.'')')
+	   RETURN
+	END IF
+
+	IF (EDITIT.AND..NOT.CLI$PRESENT('EXTRACT')
+     &	    .AND..NOT.CLI$PRESENT('FILESPEC')) THEN
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	END IF
+
+	CALL DISABLE_CTRL		! Disable CTRL-Y & -C
+
+	ALLOW = SETPRV_PRIV()
+
+	OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	OLD_FOLDER = FOLDER
+
+	LEN_P = 0
+
+	IF (CLI$PRESENT('EXTRACT')) THEN
+	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	   LEN_P = TRIM(BULL_PARAMETER)
+	   OPEN(UNIT=3,FILE=BULL_PARAMETER(:LEN_P),IOSTAT=IER,
+     &		RECL=LINE_LENGTH,
+     &		STATUS='NEW',CARRIAGECONTROL='LIST',FORM='FORMATTED')
+
+	   IF (IER.NE.0) THEN
+	      CALL ERRSNS(IDUMMY,IER)
+	      CALL SYS_GETMSG(IER)
+	      GO TO 910
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+
+	   LENI = 0
+	   IF (CLI$PRESENT('INDENT').NE.%LOC(CLI$_NEGATED)) THEN
+	      CALL CLI$GET_VALUE('INDENT',INDENT,LENI)
+	   END IF
+	   DO WHILE (ILEN.GT.0)			! Copy bulletin into file
+	      IF (LENI.EQ.0) THEN
+	         WRITE (3,'(A)') INPUT(:ILEN)
+	      ELSE
+	         WRITE (3,'(A)') INDENT(:LENI)//INPUT(:ILEN)
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END DO
+
+90	   CALL CLOSE_BULLFIL
+	END IF
+
+	SELECT_FOLDERS = .FALSE.
+	IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	   CALL GET_FOLDER_INFO(IER)
+	   IF (.NOT.IER) GO TO 910
+	   SELECT_FOLDERS = .TRUE.
+	ELSE
+	   NODE_NUM = 1
+	   NODES(1) = OLD_FOLDER
+	END IF
+
+	IF (CLI$PRESENT('FILESPEC')) THEN
+	   IER = CLI$GET_VALUE('FILESPEC',BULL_PARAMETER,LEN_P)
+	   CALL DISABLE_PRIVS
+	   IF (.NOT.CLI$PRESENT('EXTRACT')) THEN
+	      OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
+	   ELSE
+	      OPEN (UNIT=4,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
+	      IER = 0
+	      ICOUNT = 0
+	      DO WHILE (IER.EQ.0)
+		 READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		 IF (IER.EQ.0) THEN
+		    IF (ICOUNT.EQ.0) WRITE (3,'(A)') ' '
+		    ICOUNT = ICOUNT + 1
+		    WRITE (3,'(A)') INPUT(:ILEN)
+		 END IF
+	      END DO
+	      CLOSE (UNIT=4)
+	      BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	      LEN_P = TRIM(BULL_PARAMETER)
+	   END IF
+	   CALL ENABLE_PRIVS	! Reset SYSPRV privileges
+	END IF
+
+	IF (FOLDER_NUMBER.GT.0.AND.		! If folder set and
+     &	    CLI$PRESENT('NODES')) THEN		! Decnet nodes specified?
+	   WRITE (6,'('' ERROR: /NODES cannot be used with folder set.'')')
+	   GO TO 910
+	END IF
+
+	IF (.NOT.BTEST(FOLDER_FLAG,2).AND.FOLDER_NUMBER.NE.0.AND.
+     &	   (CLI$PRESENT('SYSTEM').OR.		! Is /SYSTEM switch present?
+     &	    CLI$PRESENT('BROADCAST').OR.	! Is /BROADCAST swtich present?
+     &	    CLI$PRESENT('SHUTDOWN'))) THEN	! Is /SHUTDOWN switch present?
+	   WRITE (6,'('' ERROR: Folder is not a SYSTEM folder.'')')
+	   GO TO 910
+	END IF
+
+	IF (CLI$PRESENT('SYSTEM')) THEN		! Is /SYSTEM switch present?
+	   IF (.NOT.ALLOW) THEN			! If no privileges
+	      WRITE(ERROR_UNIT,1070)		! Tell user
+	      GO TO 910				! and abort
+	   END IF
+	   SYSTEM = 1				! Set system bit
+	ELSE
+	   SYSTEM = 0				! Clear system bit
+	END IF
+
+	IF (CLI$PRESENT('BROADCAST')) THEN	! Is /BROADCAST switch present?
+	   IF (.NOT.(ALLOW.OR.OPER_PRIV())) THEN	! If no privileges
+	      WRITE(ERROR_UNIT,1080)		! Tell user
+	      GO TO 910				! and abort
+	   ELSE IF (CLI$PRESENT('CLUSTER')) THEN
+	      SYSTEM = SYSTEM.OR.8
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('PERMANENT')) THEN	! Is /PERMANENT switch present?
+	   IF (F_EXPIRE_LIMIT.GT.0.AND..NOT. ! Expiration limit present
+     &		FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	      WRITE(ERROR_UNIT,1083)
+	      GO TO 910
+	   ELSE
+	      SYSTEM = SYSTEM.OR.2		! Set permanent bit
+	      INEXDATE = '5-NOV-2100'
+	      INEXTIME = '00:00:00.00'
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SHUTDOWN')) THEN	! Is /SHUTDOWN switch present?
+	   IF (.NOT.ALLOW) THEN			! If no privileges
+	      WRITE(ERROR_UNIT,1082)		! Tell user
+	      GO TO 910				! and abort
+	   ELSE
+	      IER = CLI$GET_VALUE('SHUTDOWN',INLINE)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+		 IF (REMOTE_SET) THEN		! Can't specify node name if
+		    WRITE (6,1090)		! remote folder, as no code
+		    GO TO 910			! present to send the name.
+		 END IF
+	         CALL GET_NODE_NUMBER_OTHER(NODE_NUMBER,NODE_AREA,INLINE)
+		 IF (NODE_AREA.EQ.0) GO TO 910	! Invalid node name
+	      ELSE
+	         CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	      END IF
+	      SYSTEM = SYSTEM.OR.4		! Set shutdown bit
+	      INEXDATE = '5-NOV-2100'
+              WRITE (INEXTIME(1:),'(I2)') NODE_NUMBER/60
+              WRITE (INEXTIME(3:),'(I2)') MOD(NODE_NUMBER,60)
+              WRITE (INEXTIME(7:),'(I2)') NODE_AREA/60
+              WRITE (INEXTIME(9:),'(I2)') MOD(NODE_AREA,60)
+	      DO I=1,11
+		 IF (INEXTIME(I:I).EQ.' ') INEXTIME(I:I) = '0'
+	      END DO
+	      INEXTIME = INEXTIME(1:2)//':'//INEXTIME(3:4)//':'//
+     &			 INEXTIME(7:8)//'.'//INEXTIME(9:10)
+	   END IF
+	END IF
+
+	SELECT_NODES = .FALSE.
+	IF (CLI$PRESENT('NODES')) THEN
+	   CALL GET_NODE_INFO
+	   IF (NODE_ERROR) GO TO 940
+	   SELECT_NODES = .TRUE.
+	END IF
+
+	IF ((SYSTEM.AND.7).LE.1.AND.(CLI$PRESENT('SELECT_FOLDER').OR.
+     &	    CLI$PRESENT('NODES').OR..NOT.BTEST(FOLDER_FLAG,10))) THEN
+	   CALL GET_EXPIRED(INPUT,IER)          ! Not permanent or shutdown 
+	   IF (.NOT.IER) GO TO 910
+	   INEXDATE = INPUT(:11)
+	   INEXTIME = INPUT(13:23)
+	END IF
+
+	IF (INCMD(:3).EQ.'REP') THEN		! REPLY?
+	   LENDES = TRIM(INDESCRIP)		! filled in by main subroutine
+	ELSE IF (CLI$PRESENT('SUBJECT')) THEN	! /SUBJECT specified
+	   CALL CLI$GET_VALUE('SUBJECT',INDESCRIP,LENDES)
+	ELSE
+	   WRITE(6,1050)			! Request header for bulletin
+	   CALL GET_LINE(INDESCRIP,LENDES)	! Get input line
+	   IF (LENDES.LE.0) GO TO 910
+	END IF
+
+	LENDES = MIN(LEN(INDESCRIP)-6,LENDES)	! Make room for "Subj: "
+
+C
+C  If file specified in ADD command, read file to obtain bulletin.
+C  Else, read the bulletin from the terminal.
+C
+
+	IF (EDITIT.AND..NOT.DECNET_PROC) THEN	! If /EDIT specified
+	   IF (LEN_P.EQ.0) THEN			! If no file param specified
+	      CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 ERR=910,FORM='FORMATTED')
+	      LEN_P = 1
+	   ELSE
+	      CLOSE (UNIT=3)
+	      CALL MAILEDIT(BULL_PARAMETER(:LEN_P),'SYS$LOGIN:BULL.SCR')
+	      IF (CLI$PRESENT('EXTRACT')) THEN
+	         CONTEXT = 0
+	         CALL LIB$FIND_FILE('SYS$LOGIN:BULL.SCR',INPUT,CONTEXT)
+	         VERSION = INDEX(INPUT,';') + 1
+	         IF (INPUT(VERSION:VERSION).EQ.'1') THEN
+	            CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	         END IF
+	      END IF
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 ERR=910,FORM='FORMATTED')
+	   END IF
+	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	   LEN_P = TRIM(BULL_PARAMETER)
+	END IF
+
+	ICOUNT = 0				! Line count for bulletin
+
+	END = 0
+	BLENGTH = 35
+	IF (CLI$PRESENT('BELL')) BLENGTH = 37
+	IF (LEN_P.GT.0) THEN			! If file param in ADD command
+	   DO WHILE(1)				! Read until end of file to
+	      READ (3,'(Q,A)',END=10) ILEN,INPUT! get record count
+	      IF (ILEN.GT.LINE_LENGTH) GO TO 950
+	      ICOUNT = ICOUNT + 1 + MIN(ILEN,80)
+	      BLENGTH = BLENGTH + ILEN - 1 + 2
+	      IF (ILEN.EQ.0) ICOUNT = ICOUNT + 1! COPY_BULL writes line with
+	   END DO				! 1 space for blank line
+	ELSE					! If no input file
+	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
+	   LEN_P = TRIM(BULL_PARAMETER)
+	   OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',
+     &		STATUS='NEW',
+     &		FORM='FORMATTED',RECL=LINE_LENGTH) ! Temp file to save message
+	   WRITE (6,1000)			! Request input from terminal
+	   ILEN = LINE_LENGTH + 1		! Length of input line
+	   ICOUNT = 0				! Character count counter
+	   DO WHILE (ILEN.GE.0)			! Input until no more input
+	      CALL GET_LINE(INPUT,ILEN)		! Get input line
+	      IF (ILEN.GT.LINE_LENGTH) THEN	! Input line too long
+		 WRITE(6,'('' ERROR: Input line length > '',I,
+     &			''.  Reinput:'')') LINE_LENGTH
+	      ELSE IF (ILEN.GE.0) THEN		! If good input line entered
+		 ICOUNT = ICOUNT + ILEN		! Update counter
+	         BLENGTH = BLENGTH + ILEN - 1 + 2
+		 WRITE(3,2010) INPUT(:ILEN)	! Save line in scratch file
+	      END IF
+	   END DO
+	   IF (ILEN.EQ.-1) GO TO 910		! CTRL_C entered, error out
+10	   IF (ICOUNT.EQ.0) GO TO 910		! No lines entered, error out
+	ENDIF
+
+	REWIND (UNIT=3)
+
+	BRDCST = .FALSE.
+
+	IF (CLI$PRESENT('BROADCAST').AND.BLENGTH.GT.82*12+2) THEN
+	   WRITE (6,'('' Message is too long for broadcasting by '',
+     &	        I6,'' characters.  Limit is '',I3,''.'')')
+     &			BLENGTH - 82*12 - 2, 82*12 - 2
+	   CALL GET_INPUT_PROMPT(INPUT,ILEN,
+     &		'Type C to broadcast anyway, A to only ADD message,'
+     &   	//' or Q to Quit: ')
+	   IF (STREQ(INPUT(:1),'Q')) THEN
+	      GO TO 910
+	   ELSE IF (STREQ(INPUT(:1),'A')) THEN
+	      BRDCST = .TRUE.
+	   ELSE IF (.NOT.STREQ(INPUT(:1),'C')) THEN
+	      GO TO 910
+	   END IF
+	END IF
+
+	IF (SELECT_NODES.AND.NODE_NUM.GT.0) THEN
+	   INLINE = 'ADD'
+	   IF (CLI$PRESENT('SYSTEM'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/SYSTEM'
+	   IF (CLI$PRESENT('BROADCAST').AND..NOT.BRDCST)
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/BROADCAST'
+	   IF (CLI$PRESENT('PERMANENT'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/PERMANENT'
+	   IF (CLI$PRESENT('SHUTDOWN'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/SHUTDOWN'
+	   IF (CLI$PRESENT('BELL'))
+     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/BELL'
+
+	   LEN_INLINE = STR$POSITION(INLINE,' ') - 1
+
+	   DO POINT_NODE=1,NODE_NUM	   	! Write out command to nodes
+	      INLINE = INLINE(:LEN_INLINE)
+
+	      WRITE (POINT_NODE+9,'(A)',ERR=940) INLINE
+	      IF ((SYSTEM.AND.7).LE.1)
+				! If not permanent or shutdown specify date
+     &		WRITE (POINT_NODE+9,'(A)',ERR=940) INEXDATE//' '//INEXTIME
+	      WRITE (POINT_NODE+9,'(A)',ERR=940) INDESCRIP(:LENDES)
+	      IER = 0
+	      DO WHILE (IER.EQ.0)
+	         READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		 ILEN = MIN(ILEN,LINE_LENGTH)
+		 IF (IER.EQ.0) THEN
+		    WRITE (POINT_NODE+9,'(A)',ERR=940) INPUT(:ILEN)
+		 END IF
+	      END DO
+	      WRITE (POINT_NODE+9,'(A)',ERR=940) CHAR(26)
+	      READ (POINT_NODE+9,'(A)',ERR=940,END=940) INPUT
+	      IF (INPUT.EQ.'END') THEN
+	         WRITE (6,'('' Message successfully sent to node '',A)')
+     &				NODES(POINT_NODE)
+	      ELSE
+	         WRITE (6,'('' Error while sending message to node '',A)')
+     &				NODES(POINT_NODE)
+		 WRITE (6,'(A)') INPUT(:80)
+		 GO TO 940
+	      END IF
+	      REWIND (UNIT=3)
+	   END DO
+	END IF
+	
+	IF (SELECT_NODES.AND..NOT.LOCAL_NODE_FOUND) GO TO 95
+					! Exit if local node not specified.
+
+	IF (.NOT.SELECT_FOLDERS) THEN
+	   NODE_NUM = 1				! No folders specified so just
+	   NODES(1) = FOLDER			! add to select folder
+	END IF
+
+	IER = SYS_TRNLNM('SYS$NODE',LOCAL_NODE)
+	LNODE = TRIM(LOCAL_NODE)	
+
+C
+C  Add bulletin to bulletin file and directory entry for to directory file.
+C
+
+	DO I = 1,NODE_NUM
+
+	   IF (FOLDER.NE.NODES(I)) THEN
+	      FOLDER_NUMBER = -1
+	      FOLDER1 = NODES(I)
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	   ELSE
+	      IER = 1
+	   END IF
+	   
+	   IF (IER.AND..NOT.BTEST(FOLDER_FLAG,10)) THEN
+	      CALL OPEN_BULLDIR			! Prepare to add dir entry
+
+	      DESCRIP=INDESCRIP(:LENDES)	! Description header
+	      EXDATE=INEXDATE			! Expiration date
+	      EXTIME=INEXTIME
+	      IF (BTEST(FOLDER_FLAG,14)) THEN
+	         FROM = 'ANONYMOUS'
+              ELSE
+	         FROM = USERNAME		! Username
+	      END IF
+
+	      CALL OPEN_BULLFIL			! Prepare to add bulletin
+
+	      CALL READDIR(0,IER1)		! Get NBLOCK
+	      IF (IER1.EQ.0) NBLOCK = 0		! If new file, NBLOCK is 0
+
+	      REWIND (UNIT=3)
+	      OBLOCK = NBLOCK+1
+	      IF (.NOT.BTEST(FOLDER_FLAG,14)) THEN
+	         CALL STORE_BULL(LNODE+TRIM(FROM)+6,'From: '//
+     &		    LOCAL_NODE(:LNODE)//FROM(:TRIM(FROM)),OBLOCK)
+	      END IF
+	      IF (LENDES.GT.LEN(DESCRIP)) THEN
+	         CALL STORE_BULL(LENDES+6,
+     &			'Subj: '//INDESCRIP(:LENDES),OBLOCK)
+	      END IF
+	      CALL COPY_BULL(3,1,OBLOCK,IER1)	! Add the new bulletin
+	      IF (IER1.NE.0) GO TO 930		! Error in creating bulletin
+	      LENGTH = OCOUNT - (NBLOCK+1) + 1
+
+	      IF (.NOT.BRDCST.AND.CLI$PRESENT('BROADCAST').AND.
+     &		 (.NOT.REMOTE_SET.OR.FOLDER_NUMBER.GT.0)) THEN
+		 CALL GET_BROADCAST_MESSAGE(CLI$PRESENT('BELL'))
+	      END IF
+
+	      CALL ADD_ENTRY			! Add the new directory entry
+
+	      CALL CLOSE_BULLFIL		! Finished adding bulletin
+
+	      IF (FOLDER_NUMBER.GE.0) THEN
+	         DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &			       F_NEWEST_BTIM)
+	         CALL UPDATE_FOLDER		! Update info in folder file
+C
+C  If user is adding message, an no new messages, update last read time for
+C  folder, so user is not alerted of new message which is owned by user.
+C
+	         IF (DIFF.GE.0) THEN
+	            LAST_READ_BTIM(1,FOLDER_NUMBER+1) = F_NEWEST_BTIM(1)
+	            LAST_READ_BTIM(2,FOLDER_NUMBER+1) = F_NEWEST_BTIM(2)
+	         END IF
+		 IF (BULL_TAG.AND.BTEST(BULL_TAG,1)) THEN
+		    CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+		    CALL ADD_TAG(IER1,2)
+		 END IF
+	      END IF
+
+	      CALL CLOSE_BULLDIR		! Totally finished with add
+C
+C  Broadcast the bulletin if requested.
+C
+	      IF (.NOT.BRDCST.AND.CLI$PRESENT('BROADCAST').AND.
+     &		 (.NOT.REMOTE_SET.OR.FOLDER_NUMBER.GT.0)) THEN
+		 BRDCST = .TRUE.
+	         IF (.NOT.CLI$PRESENT('LOCAL')) THEN
+	            CALL BROADCAST_ALL_NODES(CLI$PRESENT('ALL'),
+     &			CLI$PRESENT('CLUSTER'))
+		 END IF
+C
+C  If the folder is remote, and local node is not the node which BULLCP is
+C  on, don't broadcast, as it will be broadcasted by BULLCP.  The remote
+C  node will distribute the broadcast to nodes that are running BULLCP,
+C  but not if the node that originated the message matches.  However, it
+C  has no way of knowing that the originating node is in the same cluster
+C  as that of the BULLCP node.
+C
+		 IF ((REMOTE_SET.AND.LOCAL_NODE(:LNODE-2).EQ.NODENAME)
+     &		     .OR.CLI$PRESENT('LOCAL').OR..NOT.REMOTE_SET)
+     &	            CALL BROADCAST(
+     &			CLI$PRESENT('ALL'),CLI$PRESENT('CLUSTER'))
+	      END IF
+	   ELSE IF (.NOT.IER) THEN
+	      WRITE (6,'('' ERROR: Unable to add message to '',A)')
+     &				NODES(I)
+	   END IF
+           IF (IER.AND.(BTEST(FOLDER_FLAG,10).OR.
+     &			BTEST(FOLDER_FLAG,11)).AND.REMOTE_SET.LT.3) THEN
+	      IF (NEWS_FEED()) THEN
+	         SLIST = INDEX(FOLDER_DESCRIP,'[')
+	      ELSE
+	         SLIST = INDEX(FOLDER_DESCRIP,'<')
+	      END IF
+	      IF (SLIST.GT.0) THEN
+	         INPUT = FOLDER_DESCRIP(SLIST+1:)
+	         IF (NEWS_FEED()) THEN
+	            ILEN = INDEX(INPUT,']') - 1
+	         ELSE
+	            ILEN = INDEX(INPUT,'>') - 1
+	         END IF
+	         IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+	         INPUT = INPUT(:ILEN)
+                 CALL ADD_PROTOCOL(INPUT,ILEN)
+	         CLOSE (UNIT=3,STATUS='SAVE')
+		 IF (BTEST(FOLDER_FLAG,10).OR.BTEST(FOLDER_FLAG,15)) THEN
+	            CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
+     &		       INDESCRIP(:LENDES),STATUS)
+		 ELSE
+	            CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
+     &	   	       FOLDER(:TRIM(FOLDER))//' folder message: '//
+     &		       INDESCRIP(:LENDES),STATUS)
+		 END IF
+	         IF (BULL_PARAMETER.EQ.'SYS$LOGIN:BULL.SCR') THEN
+	            OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		       ERR=910,FORM='FORMATTED')
+	         ELSE
+	            OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		       READONLY,SHARED,ERR=910,FORM='FORMATTED')
+	         END IF
+	      END IF
+	   END IF
+	END DO
+
+95	CLOSE (UNIT=3)			! Close the input file
+	IF (DECNET_PROC) WRITE(5,'(''END'')') ! DECNET operation worked
+
+	LENFRO = 0
+	DO WHILE (CLI$GET_VALUE('CC',INLINE,ILEN).NE.%LOC(CLI$_ABSENT))
+	   CALL ADD_PROTOCOL(INLINE,ILEN)
+	   IF (LENFRO.EQ.0) THEN
+	      INPUT = INLINE(:ILEN)//','
+	   ELSE
+	      INPUT = INPUT(:LENFRO)//INLINE(:ILEN)//','
+	   END IF
+	   LENFRO = LENFRO + ILEN + 1
+	END DO
+
+	IF (LENFRO.GT.1) THEN 
+	   LENFRO = LENFRO - 1
+	   I = 1		! Must change all " to "" in FROM field
+	   DO WHILE (I.LE.LENFRO)
+	      IF (INPUT(I:I).EQ.'"') THEN
+	         INPUT = INPUT(:I)//'"'//INPUT(I+1:)
+	         I = I + 1
+		 LENFRO = LENFRO + 1
+	      END IF
+	      I = I + 1
+	   END DO
+	   CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
+     &			     INDESCRIP(:LENDES),STATUS)
+	END IF
+
+100	CALL ENABLE_CTRL		! Enable CTRL-Y & -C
+	DO I=10,NODE_NUM+9
+	   CLOSE (UNIT=I)
+	END DO
+
+	IF (NEWS_FEED()) THEN
+	   SLIST = INDEX(FOLDER_DESCRIP,'<')
+	   FOLDER1_DESCRIP = 
+     &		FOLDER_DESCRIP(SLIST+1:INDEX(FOLDER_DESCRIP,'>')-1)
+	   CALL NEWS_POST(BULL_PARAMETER(:LEN_P),.FALSE.,IER,
+     &		INDESCRIP)
+	END IF
+
+200	IF (FOLDER_NUMBER.NE.OLD_FOLDER_NUMBER) THEN
+	   FOLDER_NUMBER = OLD_FOLDER_NUMBER
+	   FOLDER1 = OLD_FOLDER
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	END IF
+
+	CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+
+	RETURN
+
+910	WRITE(ERROR_UNIT,1010)
+	CLOSE (UNIT=3,ERR=100)
+	GO TO 200
+
+920	WRITE(ERROR_UNIT,1020)
+	CALL ENABLE_PRIVS
+	GO TO 200
+
+930	WRITE (ERROR_UNIT,1025)
+	CALL CLOSE_BULLFIL
+	CALL CLOSE_BULLDIR
+	CLOSE (UNIT=3)
+	GO TO 200
+
+940	WRITE (6,1015) NODES(POINT_NODE)
+	WRITE (6,1018)
+	CLOSE (UNIT=3)
+	GO TO 200
+
+950	WRITE (6,1030) LINE_LENGTH
+	CLOSE (UNIT=3)
+	GO TO 200
+
+1000	FORMAT (' Enter message: End with ctrl-z, cancel with ctrl-c')
+1010	FORMAT (' No message was added.')
+1015	FORMAT (' ERROR: Unable to reach node ',A)
+1018	FORMAT (' Try using /FOLDER instead of /NODE.')
+1020	FORMAT (' ERROR: Unable to open specified file.')
+1025	FORMAT (' ERROR: Unable to add message to file.')
+1030	FORMAT (' ERROR: Line length in file exceeds '',I,'' characters.')
+1050	FORMAT (' Enter description header.')
+1070	FORMAT (' ERROR: SETPRV privileges are needed for system
+     & messages.')
+1080	FORMAT (' ERROR: SETPRV privileges are needed to broadcast
+     & messages.')
+1082	FORMAT (' ERROR: SETPRV privileges are needed to shutdown
+     & messages.')
+1083	FORMAT (' ERROR: Folder has expiration limit.')
+1090	FORMAT (' ERROR: Nodename cannot be specified for shutdown
+     & if folder is remote.')
+2010	FORMAT(A)
+2020	FORMAT(1X,A)
+
+	END
+
+
+	SUBROUTINE SUBTIME(BTIM,DAYS_BEFORE_TODAY,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER DAYS_BEFORE_TODAY*(*),TODAY_DATE*24
+
+	INTEGER BTIM(2),TODAY_BTIM(2)
+
+	IER = SYS$BINTIM(DAYS_BEFORE_TODAY,BTIM)
+	IF (.NOT.IER) RETURN
+
+	BTIM(1) = -BTIM(1)		! Convert to negative delta time
+	BTIM(2) = -BTIM(2)-1
+
+	IER = SYS$ASCTIM(TLEN,TODAY_DATE,,)
+	CALL SYS$BINTIM(TODAY_DATE(:TLEN),TODAY_BTIM)
+
+	CALL LIB$SUBX(TODAY_BTIM,BTIM,BTIM)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE BROADCAST_ALL_NODES(ALL,CLUSTER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	PARAMETER BRDCST_LIMIT = 82*12 + 2 + 2
+	CHARACTER*(BRDCST_LIMIT) BMESSAGE
+
+	COMMON /BROAD_MESSAGE/ BMESSAGE,BLENGTH
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER RESPONSE*4
+
+	IF (.NOT.TEST_BULLCP().OR.REMOTE_SET) RETURN
+
+	CALL OPEN_BULLUSER_SHARED
+
+	REMOTE_FOUND = .FALSE.
+	TEMP_USER = ':'
+
+	DO WHILE (.NOT.REMOTE_FOUND)
+	   DO WHILE (REC_LOCK(IER))		 
+	      READ (4,KEYGT=TEMP_USER,IOSTAT=IER)
+     &		TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG
+	   END DO
+	   IF (TEMP_USER(:1).NE.':') THEN
+	      CALL CLOSE_BULLUSER
+	      RETURN
+ 	   END IF
+	   REMOTE_FOUND = TEST2(NEW_FLAG,FOLDER_NUMBER)
+	END DO
+
+	CALL CLOSE_BULLUSER
+
+100	OPEN (UNIT=17,STATUS='UNKNOWN',IOSTAT=IER,RECL=256,
+     &		FILE=NODENAME(:TRIM(NODENAME))//'::"TASK=BULLETIN1"')
+
+	IF (IER.EQ.0) THEN
+	   IER = 0
+	   I = 1
+	   DO WHILE (IER.EQ.0.AND.I.LT.BLENGTH)
+	      WRITE (17,'(4A)',IOSTAT=IER)
+     &		15,-1,I,BMESSAGE(I:MIN(BLENGTH,I+127))
+	       I = I + 128
+	   END DO
+	   IF (IER.EQ.0) WRITE (17,'(7A)',IOSTAT=IER)
+     &		15,BLENGTH,I,ALL,CLUSTER,FOLDER_NUMBER,FOLDER
+	ELSE
+	   WRITE (6,'('' BULLCP not responding to request to'',
+     &	              '' broadcast to other nodes.'')')
+	   CALL GET_INPUT_PROMPT(RESPONSE,LEN,
+     &		'Want to try again? (Y/N with Y as default): ')
+	   IF (RESPONSE(:1).NE.'n'.AND.RESPONSE(:1).NE.'N') THEN
+	      WRITE (6,'('' Trying again...'')')
+	      GO TO 100
+	   ELSE
+	      WRITE (6,'('' Broadcast aborting. '',
+     &		         ''Continuing with message addition.'')')
+	   END IF
+	END IF
+
+	CLOSE (UNIT=17)
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION ERROR_TRAP
+
+	ERROR_TRAP = 1
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REPLY
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /INDESCRIP/ INDESCRIP
+	CHARACTER*(INPUT_LENGTH) INDESCRIP
+
+	IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	   WRITE(6,'('' ERROR: You have not read any message.'')')
+	   RETURN			! And return
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+
+	IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	   WRITE(6,'('' ERROR: Bulletin was not found.'')')
+	   CALL CLOSE_BULLDIR		! If not, then error out
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLFIL_SHARED
+
+	ILEN = LINE_LENGTH + 1
+
+	CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	END IF
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	   INDESCRIP = INPUT(7:)
+	ELSE
+	   INDESCRIP = DESCRIP
+	END IF
+
+	CALL CLOSE_BULLFIL
+
+	CALL CLOSE_BULLDIR
+
+	WRITE (6,'('' Adding REPLY message with the subject:'')')
+	IF (STREQ(INDESCRIP(:3),'RE:')) THEN
+	   INDESCRIP = 'Re:'//INDESCRIP(4:)
+	ELSE
+	   INDESCRIP = 'Re: '//INDESCRIP
+	END IF
+	WRITE (6,'(1X,A)') INDESCRIP(:TRIM(INDESCRIP))
+
+	CALL ADD
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CRELNM(INPUT,OUTPUT)
+	
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PSLDEF)'
+
+	INCLUDE '($LNMDEF)'
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT))
+	CALL END_ITMLST(CRELNM_ITMLST)
+
+	IER = SYS$CRELNM(,'LNM$PROCESS',INPUT,PSL$C_USER,
+     &		%VAL(CRELNM_ITMLST))
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETPRIV
+C
+C  SUBROUTINE GETPRIV
+C
+C  FUNCTION:
+C	To get process privileges.
+C  OUTPUTS:
+C	PROCPRIV - Returned privileges
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	COMMON /REALPROC/ REALPROCPRIV(2)
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(8,JPI$_PROCPRIV,%LOC(PROCPRIV))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	REALPROCPRIV(1) = PROCPRIV(1)
+	REALPROCPRIV(2) = PROCPRIV(2)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION SETPRV_PRIV
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+	DATA NEEDPRIV/0,0/
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	IF (NEEDPRIV(1).EQ.0.AND.NEEDPRIV(2).EQ.0) THEN
+	   CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+	   CALL READ_USER_FILE_HEADER(IER)
+	   CALL CLOSE_BULLUSER
+	   NEEDPRIV(1) = USERPRIV(1)
+	   NEEDPRIV(2) = USERPRIV(2)
+	END IF
+
+	IF ((PROCPRIV(1).AND.NEEDPRIV(1)).NE.0.OR.
+     &	    (PROCPRIV(2).AND.NEEDPRIV(2)).NE.0) THEN
+	   SETPRV_PRIV = .TRUE.
+	ELSE
+	   SETPRV_PRIV = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION OPER_PRIV
+	IMPLICIT INTEGER (A-Z)
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+	INCLUDE '($PRVDEF)'
+	OPER_PRIV = BTEST(PROCPRIV(1),PRV$V_OPER)
+	RETURN
+	END
+
+
+ 
+	SUBROUTINE GETUSER(USERNAME)
+C
+C  SUBROUTINE GETUSER
+C
+C  FUNCTION:
+C	To get username of present process.
+C  OUTPUTS:
+C	USERNAME   -   Username owner of present process.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	CHARACTER*(*) USERNAME		! Limit is 12 characters
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(LEN(USERNAME),JPI$_USERNAME,%LOC(USERNAME))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION CAPTIVE(FLAG)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE '($UAIDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	DATA READ_UAI/.FALSE./
+
+	COMMON /BULL_CUSTOM/ BULL_CUSTOM
+
+	IF (BTEST(BULL_CUSTOM,FLAG)) THEN 
+	   CAPTIVE = .FALSE.
+	   RETURN
+	END IF
+
+	TYPE = 1
+
+	IF (.NOT.READ_UAI) THEN
+	   CALL INIT_ITMLST
+	   CALL ADD_2_ITMLST(4,UAI$_FLAGS,%LOC(FLAGS))
+	   CALL END_ITMLST(GETUAI_ITMLST)
+           IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+	   READ_UAI = .TRUE.
+	END IF
+
+	CAPTIVE = ((FLAGS.AND.(UAI$M_CAPTIVE.OR.UAI$M_RESTRICTED)).NE.0
+     &	  .AND.1).OR.ISHFT(((FLAGS.AND.UAI$M_NOMAIL).NE.0).AND.1,1)
+
+	RETURN
+	END
+
+
+
+
+        SUBROUTINE SPAWN_PROCESS
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+	CHARACTER*256 COMMAND
+
+	IF (CAPTIVE(-1)) THEN
+	   WRITE (6,'('' ERROR: SPAWN not allowed from CAPTIVE account.'')')
+	   RETURN
+	END IF
+
+	CALL DISABLE_PRIVS
+
+	SAVE_KEYPAD_MODE = KEYPAD_MODE
+	IF (KEYPAD_MODE.EQ.0) CALL SET_KEYPAD
+
+	IF (CLI$PRESENT('COMMAND')) THEN
+	   CALL CLI$GET_VALUE('COMMAND',COMMAND,CLEN)
+	   COMMAND = '$'//COMMAND(:CLEN)
+	   CALL LIB$SPAWN(COMMAND(:CLEN+1))
+	ELSE
+           CALL LIB$SPAWN()
+	END IF
+
+	IF (SAVE_KEYPAD_MODE.EQ.0) CALL SET_NOKEYPAD
+
+	CALL ENABLE_PRIVS
+
+	RETURN
+        END
+
+
+        SUBROUTINE ATTACH
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	INCLUDE '($JPIDEF)'
+
+	CHARACTER*16 PROCESS
+
+	IF (CLI$PRESENT('PROCESS')) THEN
+	   CALL CLI$GET_VALUE('PROCESS',PROCESS,PLEN)
+
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(4,JPI$_PID,%LOC(PROCESS_ID))
+	   CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	   IER = SYS$GETJPIW(,,PROCESS(:PLEN),%VAL(GETJPI_ITMLST),,,,)
+	ELSE
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(4,JPI$_OWNER,%LOC(PROCESS_ID))
+	   CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	   IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)
+	END IF
+
+	IER = SYS$CANCEL(%VAL(TERM_CHAN))
+
+	SAVE_KEYPAD_MODE = KEYPAD_MODE
+	IF (KEYPAD_MODE.EQ.0) CALL SET_KEYPAD
+
+	IF (IER) IER = LIB$ATTACH(PROCESS_ID)
+	IF (.NOT.IER) CALL SYS_GETMSG(IER)
+
+	IF (SAVE_KEYPAD_MODE.EQ.0) CALL SET_NOKEYPAD
+
+	RETURN
+        END
+
+
+
+
+
+	SUBROUTINE GET_BROADCAST_MESSAGE(RING_BELL)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($BRKDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+C
+C  The largest message that can be broadcasted is dependent on system
+C  and user quotas.  The following limit is 12 lines of ( 80 characters +
+C  CR/LF ) + 2 bells.  This should be more than enough room, as broadcasts
+C  shouldn't be too large anyway.
+C
+
+	PARAMETER CR=CHAR(13),LF=CHAR(10),BELL=CHAR(7)
+
+	PARAMETER BRDCST_LIMIT = 82*12 + 2 + 2
+	CHARACTER*(BRDCST_LIMIT) BROAD
+
+	COMMON /BROAD_MESSAGE/ BROAD,BLENGTH
+
+	IF (RING_BELL) THEN	! Include BELL in message?
+	   BROAD(:36) =			! Say who the bulletin is from
+     &		BELL//BELL//CR//LF//LF//'NEW BULLETIN FROM: '//FROM
+	   BLENGTH = 37			! Start adding next line here
+	ELSE
+	   BROAD(:34) =			! Say who the bulletin is from
+     &		CR//LF//LF//'NEW BULLETIN FROM: '//FROM
+	   BLENGTH = 35			! Start adding next line here
+	END IF
+
+	IF (REMOTE_SET) REWIND (UNIT=3)
+
+	END = 0
+	ILEN = LINE_LENGTH + 1
+	I = 0
+	DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	   IF (REMOTE_SET) THEN
+	      READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	      IF (IER.NE.0) RETURN
+	   ELSE
+	      CALL GET_BULL_LINE(NBLOCK+1,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0) I = I + 1
+	   IF (ILEN.GT.0.AND.(I.GT.2.OR.(INPUT(:6).NE.'From: '.AND.
+     &			INPUT(:6).NE.'Subj: '))) THEN
+	      END = BLENGTH + ILEN - 1 + 2	! Check how long string will be
+	      IF (END.GT.BRDCST_LIMIT) RETURN	! String too long?
+	      BROAD(BLENGTH:END) = CR//LF//INPUT(:ILEN)! Else add new input
+	      BLENGTH = END + 1			! Reset pointer
+	   END IF
+	END DO
+
+	RETURN
+
+	ENTRY BROADCAST(ALL,CLUSTER)
+
+	CALL SYS$SETRWM(%VAL(1))		! Don't wait if can't broadcast
+
+	IF (ALL) THEN				! Should we broadcast to ALL?
+	   IF (CLUSTER) THEN
+	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLTERMS),,,%VAL(BRK$M_CLUSTER),,%VAL(5),,)
+	   ELSE
+	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLTERMS),,,,,%VAL(5),,)
+	   END IF
+	ELSE	 				! Else just broadcast to users.
+	   IF (CLUSTER) THEN
+	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLUSERS),,,%VAL(BRK$M_CLUSTER),,%VAL(5),,)
+	   ELSE
+	       CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
+     &		%VAL(BRK$C_ALLUSERS),,,,,%VAL(5),,)
+	   END IF
+	END IF
+
+	CALL SYS$SETRWM(%VAL(0))
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_FOLDER_INFO(IER)
+C
+C  SUBROUTINE GET_FOLDER_INFO
+C
+C  FUNCTION: Obtains & verifies folder names from command line.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	CHARACTER NODE_TEMP*256
+
+	NODE_NUM = 0				! Initialize number of nodes
+	DO WHILE (CLI$GET_VALUE('SELECT_FOLDER',NODE_TEMP)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified nodes
+	   IER = SYS_TRNLNM(NODE_TEMP,NODE_TEMP)
+	   CALL STR$UPCASE(NODE_TEMP,NODE_TEMP)
+	   DO WHILE (TRIM(NODE_TEMP).GT.0)
+	      NODE_NUM = NODE_NUM + 1
+	      COMMA = INDEX(NODE_TEMP,',')
+	      IF (COMMA.GT.0) THEN
+		 NODES(NODE_NUM) = NODE_TEMP(:COMMA-1)
+		 NODE_TEMP = NODE_TEMP(COMMA+1:)
+	      ELSE
+		 NODES(NODE_NUM) = NODE_TEMP
+		 NODE_TEMP = ' '
+	      END IF
+	      NLEN = TRIM(NODES(NODE_NUM))
+	      IF (NODES(NODE_NUM)(NLEN-1:NLEN).EQ.'::') THEN
+		 NODES(NODE_NUM) = NODES(NODE_NUM)(:NLEN)//'GENERAL'
+	      END IF
+	      FOLDER_NUMBER = -1
+	      FOLDER1 = NODES(NODE_NUM)
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (.NOT.IER) THEN
+		 WRITE (6,'('' Unable to access folder '',A)')
+     &				NODES(NODE_NUM)
+		 RETURN
+	      ELSE IF (READ_ONLY) THEN
+		 WRITE (6,'('' ERROR: No write access for folder '',A)')
+     &				NODES(NODE_NUM)
+		 IER = 0
+		 RETURN
+	      END IF
+	   END DO
+	END DO
+
+	IER = 1
+
+	RETURN
+	END
+	
+
+
+
+	SUBROUTINE INIT_BULLETIN(NOX)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /READIT/ READIT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING /.FALSE./
+	DATA PAGE_LENGTH/24/,PAGE_WIDTH/80/
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	EXTERNAL ERROR_TRAP
+	EXTERNAL BULLETIN_MAINCOMMANDS,ENABLE_CTRL_EXIT
+	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED
+
+	PARAMETER PCB$M_BATCH = '4000'X
+	PARAMETER PCB$M_NETWRK = '200000'X
+	PARAMETER LIB$M_CLI_CTRLY = '2000000'X
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /DEF_PROT/ ORIGINAL_DEF_PROT
+
+	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
+	CHARACTER*44 PROMPT
+
+	COMMON /BULL_CUSTOM/ BULL_CUSTOM
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/
+
+	COMMON /DCL/ DCL_CMD,DCL_COMMAND
+	CHARACTER DCL_CMD*132
+
+	IER = SYS_TRNLNM_SYSTEM('BULL_CUSTOM',BULL_PARAMETER)	
+	IF (IER) IER = OTS$CVT_TZ_L(BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+     &		,BULL_CUSTOM,,,%VAL(1)) 
+
+	CALL LIB$GET_FOREIGN(INCMD)
+	DCL_COMMAND = INDEX(INCMD,' "').GT.0.OR.INCMD(:1).EQ.'"'
+
+	CALL LIB$ESTABLISH(ERROR_TRAP)
+        IF (.NOT.CLI$GET_VALUE('PROMPT',COMMAND_PROMPT,ILEN)) THEN
+           CALL LIB$REVERT
+           CALL CLI$GET_VALUE('$LINE',COMMAND_PROMPT,ILEN)
+	   INCMD = 'BULLETIN '//INCMD
+           CALL CLI$DCL_PARSE(INCMD,BULLETIN_MAINCOMMANDS)
+        ELSE
+           CALL LIB$REVERT
+        END IF
+
+	IF (DCL_COMMAND) THEN
+	   IER = CLI$GET_VALUE('SELECT_FOLDER',DCL_CMD,LENP)
+	   IF (LENP.GT.0) THEN
+	      IF (DCL_CMD(LENP:LENP).EQ.'"') DCL_CMD = DCL_CMD(:LENP-1)
+	      IF (DCL_CMD(:1).EQ.'"') DCL_CMD = DCL_CMD(2:)
+	   END IF
+	END IF
+
+	READIT = 0
+
+	LOGIN_SWITCH = CLI$PRESENT('LOGIN')
+	SYSTEM_SWITCH = CLI$PRESENT('SYSTEM')
+	REVERSE_SWITCH = CLI$PRESENT('REVERSE')
+
+	IER = LIB$SYS_TRNLOG('BULL_DISABLE',LEN_P,BULL_PARAMETER)
+	IF (IER.EQ.1.AND.LEN_P.GT.0.AND..NOT.CLI$PRESENT('STOP')
+     &	    .AND.BULL_PARAMETER(:LEN_P).NE.'ENABLE') THEN
+	   IF (.NOT.LOGIN_SWITCH) THEN
+	      WRITE (6,'('' BULLETIN temporarily disabled. Try later.'')')
+	   END IF
+	   CALL EXIT
+	END IF
+
+	CALL SYS$SETDFPROT(,ORIGINAL_DEF_PROT)
+		! Save original default protection in case it gets changed
+
+	CALL DCLEXH(%LOC(ENABLE_CTRL_EXIT))		! Declare exit handler
+
+C
+C  Check to see if CONTROL Y disabled.  If so, then never disable CONTROL Y.
+C  Disabling and enabling CONTROL Y is done so that a person can not break
+C  while one of the data files is opened, as that would not allow anyone
+C  else to modify the files.  However, if CONTROL Y is already disabled,
+C  this is not necessary, and should not be done!
+C
+
+	CALL LIB$DISABLE_CTRL(LIB$M_CLI_CTRLY,CTRLY)	! Disable CTRL-Y & -C
+	CTRLY = CTRLY .AND. LIB$M_CLI_CTRLY
+	CALL GETPRIV				! Check privileges
+	IF (NOX) CALL CHECK_PRIV_IO(ERR)			! Check privileges on output I/O
+	CALL CHECK_DIR_ACCESS()			! Check access to directories
+	CALL LIB$ESTABLISH(ERROR_TRAP)
+        IF (CLI$GET_VALUE('LIBRARY',BULL_PARAMETER,LEN_P)) THEN
+	   FOLDER_DIRECTORY = BULL_PARAMETER(:LEN_P)
+	   CALL CHECK_DIR(BULL_PARAMETER,.FALSE.)
+	   FOLDER_DIRECTORY = BULL_PARAMETER
+	   CALL ADD_DIRECTORIES
+        END IF
+        CALL LIB$REVERT
+	CALL LIB$ENABLE_CTRL(CTRLY,)		! Renable CTRLY-Y & -C
+
+	IF (ERR.EQ.1) CALL EXIT			! I/O privilege error, so exit
+
+	CALL GETUSER(USERNAME)		! Get the process's username
+	IF (.NOT.LOGIN_SWITCH) CALL CHECK_BULLETIN_PRIV(USERNAME)
+					! Check if has bulletin privileges
+
+	I = 1				! Strip off folder name if specified
+	DO WHILE (I.LE.ILEN)
+	   IF (COMMAND_PROMPT(I:I).EQ.' ') THEN
+	      COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
+	      I = ILEN + 1
+	   ELSE IF (COMMAND_PROMPT(I:I).EQ.'/') THEN
+	      COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
+	      I = ILEN + 1
+	   ELSE
+	      I = I + 1
+	   END IF
+	END DO
+	ILEN = 1			! Get executable name to use as prompt
+	DO WHILE (ILEN.GT.0)
+	   ILEN = MAX(INDEX(COMMAND_PROMPT,':'),INDEX(COMMAND_PROMPT,']'))
+	   IF (ILEN.GT.0) THEN
+	      COMMAND_PROMPT = COMMAND_PROMPT(ILEN+1:)
+	   ELSE
+	      DO I=TRIM(COMMAND_PROMPT),1,-1
+		 IF (COMMAND_PROMPT(I:I).LT.'A'.OR.
+     &			COMMAND_PROMPT(I:I).GT.'Z') THEN
+		    COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
+		 END IF
+	      END DO
+	   END IF
+	END DO
+	COMMAND_PROMPT = COMMAND_PROMPT(:TRIM(COMMAND_PROMPT))//'> '
+	IF (COMMAND_PROMPT.EQ.'RUN> '.OR.COMMAND_PROMPT.EQ.'RU> '.OR.
+     &	    COMMAND_PROMPT.EQ.'R> ') COMMAND_PROMPT = 'BULLETIN> '
+
+	CALL INIT_COMPRESS
+
+	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//FOLDER
+
+	CALL CLI$GET_VALUE('SEPARATE',SEPARATE)
+
+	IF (CLI$PRESENT('EDIT')) EDIT_DEFAULT = .TRUE.	! /EDIT switch test
+
+	CALL FIND_BULLCP			! See if BULLCP is running
+
+	IF (CLI$PRESENT('CLEANUP')) THEN	! Test for /CLEANUP switch
+	   CALL CLI$GET_VALUE('CLEANUP',BULL_PARAMETER,LEN_P) ! Get folder #
+	   READ (BULL_PARAMETER,'(I<LEN_P>)') FOLDER_NUMBER
+	   CALL SELECT_FOLDER(.FALSE.,IER)	! Select folder
+	   CALL CLEANUP_BULLFILE		! Cleanup empty blocks
+	   CALL EXIT				! all done with cleanup
+	ELSE IF (CLI$PRESENT('BBOARD')) THEN	! Test for /BBOARD switch
+	   CALL BBOARD				! look for BBOARD mail
+	   CALL EXIT				! all done with BBOARD
+	ELSE IF (CLI$PRESENT('STARTUP').OR.	! BULLCP process control
+     &	         CLI$PRESENT('STOP')) THEN
+	   CALL CREATE_BULLCP
+	ELSE IF (CLI$PRESENT('BULLCP')) THEN	! This is BULLCP, so start
+	   IF (.NOT.CLI$GET_VALUE('SELECT_FOLDER',
+     &				BULL_PARAMETER,LENP)) THEN
+	      CALL RUN_BULLCP			! doing what BULLCP does!
+	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'NEWS') THEN
+	      CALL NEWS2BULL(.FALSE.)
+	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'NEWS1') THEN
+	      CALL NEWS2BULL(.TRUE.)
+	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'SMTP') THEN
+	      CALL SEND_MAIL
+	   END IF
+	END IF
+
+	CALL GETSTS(STS)			! Get process status word
+
+	IF (SYSTEM_SWITCH.OR.LOGIN_SWITCH) THEN	! If BULLETIN/LOGIN or /SYSTEM
+	   IF ((STS.AND.PCB$M_BATCH).GT.0) CALL EXIT	! If BATCH, exit
+	   IF (NOX) CALL CRELNM('SYS$INPUT','TT')	! Input from terminal
+	END IF
+
+	IF ((STS.AND.PCB$M_NETWRK).EQ.0) THEN
+	   DECNET_PROC = .FALSE.
+	   ERROR_UNIT = 6
+
+	   IF (NOX) CALL ASSIGN_TERMINAL		! Assign terminal
+
+           CALL LIB$ESTABLISH(ERROR_TRAP)       ! Do again due to possible
+           IF (.NOT.CLI$PRESENT('PROMPT')) THEN ! KEYPAD init file.
+              CALL LIB$REVERT
+              CALL CLI$DCL_PARSE(INCMD,BULLETIN_MAINCOMMANDS)
+           ELSE
+              CALL LIB$REVERT
+           END IF
+
+	   IF (.NOT.LOGIN_SWITCH) THEN
+	      INCMD = 'SELECT'	! Causes nearest folder name to be selected
+	      CALL SELECT_FOLDER(.FALSE.,IER)	! Select GENERAL folder
+	      IF (.NOT.IER) RETURN			! If can't access, exit
+
+	      IF (.NOT.TEST_BULLCP()) CALL DELETE_EXPIRED
+						! Delete expired messages
+	   END IF
+
+C
+C  Get user info stored in SYS$LOGIN.  Currently, this simply stores
+C  the time of the latest message read for each folder.
+C
+
+	   CALL OPEN_USERINFO
+
+	   CALL OPEN_OLD_TAG
+
+	   IF (.NOT.NOX) THEN
+	      CALL NEW_MESSAGE_NOTIFICATION
+	      RETURN
+	   END IF
+
+C
+C  Get page size for the terminal.
+C
+
+	   CALL GETPAGSIZ(PAGE_LENGTH,PAGE_WIDTH)
+
+	   IER = CLI$GET_VALUE('WIDTH',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) PAGE_WIDTH
+	   END IF
+
+	   IF (CLI$PRESENT('PAGE')) PAGING = .TRUE.
+	   IF ((STS.AND.PCB$M_BATCH).GT.0) THEN
+	      PAGING = .FALSE.
+	      PAGE_WIDTH = 80
+	   END IF
+
+	   IF (SYSTEM_SWITCH) THEN
+	      IER = CLI$GET_VALUE('SYSTEM',BULL_PARAMETER,LEN_P)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Days specified?
+	         CALL SUBTIME(SYSTEM_LOGIN_BTIM,BULL_PARAMETER(:LEN_P),IER)
+		 IF (.NOT.IER) THEN
+		    WRITE (6,'('' ERROR: Invalid parameter in /SYSTEM.'')')
+		    CALL EXIT
+		 END IF
+	      END IF
+	      IF (.NOT.LOGIN_SWITCH) THEN
+	         CALL MODIFY_SYSTEM_LIST(0)
+                 CALL READ_IN_FOLDERS
+		 FOLDER_Q = SAVE_FOLDER_Q1
+		 DO I = 1,SAVE_FOLDER_NUM
+	   	    CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	            IF (TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+		       CALL SHOW_SYSTEM
+		    END IF
+	         END DO
+	      END IF
+	   END IF
+
+C
+C  If /LOGIN, display SYSTEM bulletins and subject of non-SYSTEM bulletins.
+C
+
+	   IF (LOGIN_SWITCH.OR.SYSTEM_SWITCH) THEN	! Is /LOGIN present?
+	      CALL LOGIN			! Display SYSTEM bulletins
+	      IF (READIT.EQ.0) CALL EXIT	! If no READNEWs not set, exit
+	   END IF
+
+C
+C  If new bulletins have been added since the last time bulletins have been
+C  read, position bulletin pointer so that next bulletin read is the first new
+C  bulletin, and alert user.  If READNEW set and no new bulletins, just exit.
+C
+
+	   IF (.NOT.DCL_COMMAND) CALL NEW_MESSAGE_NOTIFICATION
+	ELSE
+	   IF (TEST_BULLCP()) CALL EXIT
+	   DECNET_PROC = .TRUE.
+	   ERROR_UNIT = 5
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin.hlp b/decus/vmslt98a/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..8479322b066d027b272d870144184edbbae1c7b2
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin.hlp
@@ -0,0 +1,151 @@
+1 BULLETIN
+Invokes  the  PFC  BULLETIN  Utility.  This utility is used for reading,
+adding and deleting message.  Users are notified at login time that new
+messages have been added and the topics of those messages are displayed.
+Reading of those messages is optional.  (Use  the  command  SET  READNEW
+while  in BULLETIN for setting automatic reading.)  Privileged users can
+add system bulletins that are displayed in full at  login  time.   These
+messages  are  also  saved,  and  can be read by BULLETIN.  Messages are
+automatically deleted after a specified expiration  date,  or  they  can
+manually  be  deleted  by  either  the  submitter  of  the  message or a
+privileged user.
+
+ Format:
+
+      BULLETIN [foldername or bulletin interactive command]
+
+BULLETIN has an interactive help  available  while  using  the  utility.
+Type HELP after invoking the BULLETIN command.
+
+If so configured, BULLETIN can also read USENET NEWS.
+2 Description
+
+The  BULLETIN  utility  is  a  utility to display messages to users when
+logging in.  Users are notified of  messages  only  once.   They're  not
+forced into reading them every time they log in.  Submitting and reading
+messages is easy to do via a utility similar to the  VMS  MAIL  utility.
+Privileged users can create messages which are displayed in full. (known
+as SYSTEM  messages).   Non-privileged  users  may  be  able  to  create
+non-SYSTEM  messages  (unless  your  system  manager  has  disabled  the
+feature), but only topics are displayed at login.
+
+Folders can be created so that messages pertaining to a single topic can
+be  placed  together.   Folders  can be made private so that reading and
+writing is limited to only users  or  groups  who  are  granted  access.
+Alternatively,  folders  can  be  made  semi-private in that everyone is
+allowed to read them but write access is limited.
+
+When new non-system messages are displayed, an optional feature which  a
+user  may  enable  will cause BULLETIN to ask whether the user wishes to
+read the new bulletins. The user can then read the  messages  (with  the
+ability  to  write any of the messages to a file). A user can enable the
+notification and prompting of new  messages  feature  on  a  folder  per
+folder  basis.   However,  the  exception  is  messages submitted to the
+default GENERAL folder.  Users are  always  notified  at  login  of  new
+bulletins  in  this  folder,  but can disable the prompting.  This is to
+give non-privileged users some ability to force  a  notification  of  an
+important message.
+
+Messages have expiration dates and times, and are deleted automatically.
+Expiration dates and  times  can  be  specified  in  absolute  or  delta
+notation.   Privileged  users  can  specify  "SHUTDOWN"  messages,  i.e.
+messages  that  get  deleted  after  a  system  shutdown  has  occurred.
+"PERMANENT" messages can also be created which never expire.
+
+Privileged users can broadcast their message (to either all users or all
+terminals).
+
+A user can select, on a folder per  folder  basis,  to  have  a  message
+broadcast  to  their  terminal  immediately  notifying  them  when a new
+message has been added.
+
+An optional "Bulletin Board" feature allows messages to  be  created  by
+users  of  other  systems  connected  via  networks.   A username can be
+assigned to a folder, and any mail sent to that  user  is  converted  to
+messages  and  stored  in  that  folder.   This  feature  originally was
+designed to duplicate the message board  feature  that  exists  on  some
+Arpanet  sites.  However, with the addition of folders, another possible
+use is to assign an Arpanet mailing list to a folder. For  example,  one
+could  have  an  INFOVAX folder associated with an INFOVAX username, and
+have INFO-VAX mail sent to INFOVAX.  Users could then read  the  mailing
+list  in  that  folder,  rather  than having INFO-VAX sent to each user.
+Optionally, the input for the bulletin board can be directed to be taken
+from  any  source other than VMS MAIL.  This might be useful if incoming
+mail is stored in a different place other than VMS MAIL.
+
+Messages can be either sent to a file, to a print queue,  or  mailed  to
+another user.
+
+BULLETIN  can  also  act a USENET NEWS reader if the appropriate network
+software is available to interact with.  See the installation notes  for
+more detail.
+2 Parameters
+The  parameter  following  the  BULLETIN  command  is interpreted as the
+folder name which should be selected, rather than  the  default  GENERAL
+folder.   If  the  parameter is specified with quotes ("parameter"), the
+parameter is  interpreted  as  an  interactive  BULLETIN  command,  i.e.
+commands  which are entered once BULLETIN is executed, i.e. "DIRECTORY",
+"ADD", etc.  BULLETIN will exit immediately after entering that command,
+rather than prompting for another command.  More than one command can be
+specified by separating the  commands  with  semi-colons,  i.e.  "SELECT
+DATA;DIR".  If the last command ends with a semi-colon, then BULLETIN 
+will not exit, but instead will enter the standard interactive mode and
+prompt the user for commands.
+2 /EDIT
+Specifies that all ADD or REPLACE commands within BULLETIN will select
+the editor for inputting text.
+2 /KEYPAD
+ /[NO]KEYPAD
+Specifies that keypad mode is to be set on, such that the keypad keys
+correspond to BULLETIN commands.  The default is /KEYPAD.
+2 /LIBRARY
+ /LIBRARY=library
+
+Specifies the library of folders to use.  By default there is  only  one
+library.  However, the system manager may decide to create more than one
+library, with each library saved in a different directory.  Use the SHOW
+LIBRARY/ALL command within BULLETIN to see if there are other libraries. 
+2 /PAGE
+ /[NO]PAGE
+
+Specifies  whether BULLETIN will stop outputting when it displays a full
+screen or not.  /PAGE is the default.   If  /NOPAGE  is  specified,  any
+output  will  continue  until it finishes.  This is useful if you have a
+terminal which can store several screenfuls of display in its memory.
+2 /PGFLQUOTA
+   /PGFLQUOTA=pages
+
+Used if you want to specify the page file quota for the BULLCP process.
+2 /STARTUP
+Starts up a detached process which will periodically check for expired
+messages, cleanup empty space in files, and convert BBOARD mail to
+messages.  This is recommended to avoid delays when invoking BULLETIN.
+It will create a process with the name BULLCP.  For clusters, this
+need be done only on one node.  On all other nodes, the system logical
+name BULL_BULLCP should be defined (to anything) in order that BULLETIN
+is aware that it is running on another node. (On the local node where
+BULLCP is running, this logical name is automatically defined.)
+2 /STOP
+Stops the BULLCP process without restarting a new one.  (See /STARTUP
+for information on the BULLCP process.)
+2 /SYSTEM
+   /SYSTEM=[days]
+
+Displays system messages that have been recently added.  The default is
+to show the messages that were added during the last 7 days.  This can
+be modified by specifying the number of days as the parameter.
+This command is useful for easily redisplaying system messages that
+might have been missed upon logging in (or were broadcasted but were
+erased from the screen.)
+2 /WIDTH
+   /WIDTH=page_width
+
+Specifies the terminal width for display purposes.  This is used if your
+startup procedure is configured such that BULLETIN/LOGIN is executed before
+the terminal type is known, and the default width is larger than what the
+terminal type actually is.  I.e. the default width might be 132, but the
+real width is 80.  In that case, you should add /WIDTH=80 to BULLETIN/LOGIN.
+2 /WSEXTENT
+   /WSEXTENT=pages
+
+Used if you want to specify the working set limit for the BULLCP process.
diff --git a/decus/vmslt98a/bulletin/bulletin.lnk b/decus/vmslt98a/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..135555ed0d09b710d55fc2a4251402df58846022
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin.lnk
@@ -0,0 +1,18 @@
+$ ULIB = "NONE"
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .NES. "" THEN GOTO LINK
+$ IF F$TRNLNM("TWG$TCP") .EQS. "" THEN GOTO LINK
+$ ULIB = "PROCESS"
+$ DEFINE/USER LNK$LIBRARY TWG$TCP:[NETDIST.LIB]LIBNET
+$ DEFINE/USER LNK$LIBRARY_1 TWG$TCP:[NETDIST.LIB]LIBNETACC
+$ DEFINE/USER LNK$LIBRARY_2 TWG$TCP:[NETDIST.LIB]LIBNET
+$LINK:
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN GOTO ALINK
+$ LINK/NOTRACE BULL/LIB/INC=BULLETIN$MAIN,SYS$SYSTEM:SYS.STB/SEL-
+        /USERLIB='ULIB'/EXE=BULLETIN,SYS$INPUT/OPT
+SYS$SHARE:VAXCRTL/SHARE
+ID="V2.24"
+$ EXIT
+$ALINK:
+$ LINK/NOTRACE/NONATIVE_ONLY BULL/LIB/INC=BULLETIN$MAIN/SYSEXE-
+       /USERLIB='ULIB'/EXE=BULLETIN,SYS$SHARE:VAXCRTL/LIB,SYS$INPUT/OPT
+ID="V2.24"
diff --git a/decus/vmslt98a/bulletin/bulletin0.for b/decus/vmslt98a/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..98263c40e765c9b059e1e5d2ddeb442aa229c4d4
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin0.for
@@ -0,0 +1,2520 @@
+C
+C  BULLETIN0.FOR, Version 9/20/96
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE DELETE_MSG
+C
+C  SUBROUTINE DELETE_MSG
+C
+C  FUNCTION:  Deletes a bulletin entry from the bulletin file.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER ANSWER*4,REMOTE_USER*12,SUBJECT*56
+
+	IMMEDIATE = 0
+	IF (CLI$PRESENT('IMMEDIATE')) THEN
+	   IF (REMOTE_SET.EQ.4) THEN
+	      WRITE (6,'('' IMMEDIATE not valid for news group.'')') 
+	      RETURN
+	   ELSE
+	      IMMEDIATE = 1
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('NODES')) THEN	! Delete messages on DECNET node?
+	   CALL DELETE_NODE		! Yes...
+	   RETURN
+	ELSE IF (DECNET_PROC) THEN	! Is this from remote node?
+	   IER = CLI$GET_VALUE('SUBJECT',SUBJECT,SLEN)
+	   CALL STR$UPCASE(SUBJECT,SUBJECT)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(0,IER)
+	   DEL_BULL = 0
+	   IER = 1
+	   DO WHILE (DEL_BULL+1.EQ.IER)
+	      DEL_BULL = DEL_BULL + 1
+	      CALL READDIR(DEL_BULL,IER)
+	      CALL STR$UPCASE(DESCRIP,DESCRIP)
+	      IF (DEL_BULL+1.EQ.IER.AND.USERNAME.EQ.FROM
+     &		   .AND.INDEX(DESCRIP,SUBJECT(:SLEN)).GT.0) THEN
+	         CALL REMOVE_ENTRY(DEL_BULL,DEL_BULL,DEL_BULL,IMMEDIATE)
+		 CALL CLOSE_BULLDIR
+	         WRITE (5,'(''END'')')	! Tell DECNET that delete went ok.
+		 RETURN
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLDIR		! Specified message not found,
+	   WRITE(ERROR_UNIT,1030)	! so error out.
+	   RETURN
+	END IF
+
+C
+C  Get the bulletin number to be deleted.
+C
+
+	IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	   CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+	ELSE IF (CLI$PRESENT('ALL')) THEN
+	   SBULL = 1
+	   EBULL = F_NBULL
+	   IER = 0
+	ELSE IF (BULL_POINT.EQ.0) THEN	! No.  Have we just read a bulletin?
+	   WRITE(6,1010)		! No, then error.
+	   RETURN
+	ELSE
+	   SBULL = BULL_POINT		! Delete the file we are reading
+	   EBULL = SBULL
+	   IER = 0
+	END IF
+
+	IF (SBULL.LE.0.OR.IER.NE.0) THEN
+	   WRITE (6,1020)
+	   RETURN
+	ELSE IF (EBULL.GT.F_NBULL.AND..NOT.REMOTE_SET.AND.
+     &						SBULL.NE.EBULL) THEN
+	   WRITE (6,'('' Last message specified > number in folder.'')')
+	   WRITE (6,'('' Do you want to delete to end of folder? '',$)')
+	   READ (5,'(A)',IOSTAT=IER) ANSWER
+	   CALL STR$UPCASE(ANSWER,ANSWER)
+	   IF (ANSWER(:1).NE.'Y') THEN
+	      WRITE (6,'('' Deletion aborted.'')')
+	      RETURN
+	   ELSE
+	      EBULL = F_NBULL
+	   END IF
+	END IF
+
+C
+C  Check to see if specified bulletin is present, and if the user
+C  is permitted to delete the bulletin.
+C
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   IF (SBULL.NE.EBULL) THEN
+	      WRITE (6,1025)
+	      RETURN
+	   END IF
+	   IER1 = SBULL + 1
+	   IF (SBULL.NE.BULL_POINT) CALL READDIR(SBULL,IER1)
+	   SUBJECT = DESCRIP
+	   IER2 = 0
+	   IF (IER2.EQ.0.AND.IER1.EQ.SBULL+1) CALL 
+     &	    REMOTE_DELETE(SBULL,IMMEDIATE,SUBJECT,I,FOLDER1_COM,IER)     
+	   IF (IER.EQ.0.AND.REMOTE_SET.LT.3) THEN
+	      IF (I.EQ.LEN(FOLDER1_COM)) THEN
+	         IER = SYS$ASCTIM(,INPUT,F1_NEWEST_BTIM,)
+	         NEWEST_EXDATE = INPUT(:11)
+	         NEWEST_EXTIME = INPUT(13:23)
+	         NBULL = F1_NBULL
+	   	 CALL UPDATE_FOLDER
+	      ELSE
+	  	 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      END IF
+	   ELSE IF (IER.NE.0) THEN
+	      CALL DISCONNECT_REMOTE
+	   END IF
+	   RETURN
+	ELSE IF (REMOTE_SET.EQ.3) THEN
+	   BULL_DELETE = SBULL - 1
+	   IER = 0
+	   IF (CLI$PRESENT('REASON')) THEN 
+	      CALL CLI$GET_VALUE('REASON',BULL_PARAMETER,LEN_P)
+	   END IF
+	   DO WHILE (BULL_DELETE.LT.EBULL)
+	      BULL_DELETE = BULL_DELETE + 1
+	      DO WHILE (BULL_DELETE+1.NE.IER)
+	         CALL READDIR(BULL_DELETE,IER)	! Get info for bulletin
+	         IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	            BULL_DELETE = BULL_DELETE + 1
+	            IF (BULL_DELETE.GT.EBULL) RETURN
+	            IF (EBULL.EQ.SBULL) THEN
+		       WRITE(6,1030) 
+	               RETURN
+		    END IF
+	         END IF
+	      END DO
+	      SUBJECT = DESCRIP
+	      IF (.NOT.TEST_NEWS_OWNER().AND.SETPRV_PRIV().AND.
+     &		  .NOT.CLI$PRESENT('FORCE')) THEN
+ 	         SUBJECT = 'CanceL'
+	         IF (CLI$PRESENT('REASON')) THEN 
+		    SUBJECT = SUBJECT(:6)//BULL_PARAMETER(:LEN_P)
+		 END IF
+	      END IF
+	      CALL REMOTE_DELETE
+     &			(SBULL,IMMEDIATE,SUBJECT,I,FOLDER1_COM,IER)     
+	      IF (IER.NE.0) THEN
+		 CALL DISCONNECT_REMOTE
+	   	 RETURN
+	      END IF
+	   END DO
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLDIR
+
+	CALL READDIR(0,IER)
+
+	BULL_DELETE = SBULL - 1
+	DO WHILE (BULL_DELETE.LT.EBULL)
+	   BULL_DELETE = BULL_DELETE + 1
+	   DO WHILE (BULL_DELETE+1.NE.IER)
+	      CALL READDIR(BULL_DELETE,IER)	! Get info for bulletin
+	      IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	         IF (REMOTE_SET.EQ.4) THEN
+	            BULL_DELETE = BULL_DELETE + 1
+	            IF (BULL_DELETE.GT.EBULL) THEN
+		       CALL CLOSE_BULLDIR
+		       RETURN
+		    END IF
+	         ELSE
+	            IF (.NOT.CLI$PRESENT('ALL')) WRITE(6,1030) 
+	            CALL CLOSE_BULLDIR		! If not, then error out
+	            RETURN
+	         END IF
+	      END IF
+	   END DO
+
+	   SUBJECT = DESCRIP
+
+	   IF (USERNAME.NE.FROM.OR.(REMOTE_SET.EQ.4.AND.
+     &		.NOT.TEST_NEWS_OWNER())) THEN
+	      CALL STR$UPCASE(REMOTE_USER,FROM)
+	      IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.    ! Privileges?
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN
+	         WRITE(6,1040)		! No, then error out.
+	         CALL CLOSE_BULLDIR
+		 RETURN
+	      ELSE IF (SBULL.EQ.EBULL) THEN
+		 IF (TRIM(FROM).EQ.1) THEN
+		    CALL OPEN_BULLFIL
+	            ILEN = LINE_LENGTH + 1
+	            CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	            CALL CLOSE_BULLFIL
+	            ASK = ILEN.EQ.0.OR.INPUT(:6).NE.'From: '
+		 ELSE
+		    ASK = REMOTE_USER.NE.USERNAME
+		 END IF
+		 IF (ASK.AND..NOT.CLI$PRESENT('FORCE')) THEN
+	            CALL CLOSE_BULLDIR
+	            WRITE (6,1050)	! Make sure user wants to delete it
+	            READ (5,'(A)',IOSTAT=IER) ANSWER
+	            CALL STR$UPCASE(ANSWER,ANSWER)
+	            IF (ANSWER(:1).NE.'Y') RETURN
+	            CALL OPEN_BULLDIR
+	            CALL READDIR(BULL_DELETE,IER)
+	            IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	               WRITE(6,1030)	! If not, then error out
+	               CALL CLOSE_BULLDIR
+		       RETURN
+	            END IF
+		    IF (REMOTE_SET.EQ.4) THEN 
+ 	               SUBJECT = 'CanceL'
+		    END IF
+	         END IF
+	      END IF
+	   END IF
+
+C
+C  Delete the bulletin directory entry.
+C
+	   CALL REMOVE_ENTRY(BULL_DELETE,SBULL,EBULL,IMMEDIATE)
+	   IF (REMOTE_SET.EQ.4) THEN
+	      IF (.NOT.CLI$PRESENT('LOCAL').AND.(TEST_NEWS_OWNER().OR.
+     &		  SETPRV_PRIV())) THEN
+	         CALL REMOTE_DELETE
+     &		    (BULL_DELETE,IMMEDIATE,SUBJECT,I,FOLDER1_COM,IER)
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLDIR
+	RETURN
+
+1010	FORMAT(' ERROR: You are not reading any message.')
+1020	FORMAT(' ERROR: Specified message number has incorrect format.')
+1025	FORMAT(' ERROR: Cannot delete multiple messages in remote folder.')
+1030	FORMAT(' ERROR: Specified message was not found.')
+1040	FORMAT(' ERROR: Message was not deleted. Not owned by you.')
+1050	FORMAT(' Message is not owned by you.',
+     &	       ' Are you sure you want to delete it? ',$)
+
+	END
+
+
+
+	SUBROUTINE REMOVE_ENTRY(BULL_DELETE,SBULL,EBULL,IMMEDIATE)
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	INTEGER NOW(2),EX(2)
+
+	IF (IMMEDIATE.EQ.1) THEN		! Delete it immediately
+
+	   CALL DELETE_ENTRY(BULL_DELETE)	! Delete the directory entry
+
+	   IF ((SYSTEM.AND.4).EQ.4) THEN	! Was entry shutdown bulletin?
+	      SHUTDOWN = SHUTDOWN - 1		! Decrement shutdown count
+	   END IF
+	ELSE				! Delete it eventually
+C
+C  Change year of expiration date of message to 100 years less,
+C  to indicate that message is to be deleted.  Then, set expiration date
+C  in header of folder to 15 minutes from now.  Thus, the folder will be
+C  checked in 15 minutes (or more), and will delete the messages then.
+C
+C  NOTE: If some comic set their expiration date to > 1999, then
+C  the deleted date will be set to 1899 since can't specify date <1859.
+C
+
+	   IF ((SYSTEM.AND.7).LE.1) THEN	! General or System message
+	      IF (EXDATE(8:9).EQ.'19') EXDATE(8:9) = '18'
+	      IF (EXDATE(8:9).EQ.'20') EXDATE(8:9) = '19'
+	      IF (EXDATE(8:9).EQ.'18'.AND.EXDATE(10:10).LT.'6')
+     &			EXDATE(10:11) = '99'
+	   ELSE				! Permanent or Shutdown
+	      IF (EXDATE(2:2).EQ.'-') THEN
+	         EXDATE = EXDATE(:6)//'19'//EXDATE(9:)
+	      ELSE
+	         EXDATE = EXDATE(:7)//'19'//EXDATE(10:)
+	      END IF
+	   END IF
+
+	   CALL WRITEDIR(BULL_DELETE,IER)	! Update message expiration date
+
+	   IER = SYS$BINTIM('0 0:15',EX)	! Get time 15 minutes from now
+	   IER = SYS$GETTIM(NOW)
+	   IER = LIB$SUBX(NOW,EX,EX)
+	   IER = SYS$ASCTIM(,INPUT,EX,)
+
+	END IF
+
+	IF (IMMEDIATE.NE.1.AND.BULL_DELETE.EQ.EBULL) THEN
+	   CALL READDIR(0,IER)			! Get header
+
+	   NEWEST_EXDATE = INPUT(:11)		! and store new expiration date
+	   NEWEST_EXTIME = INPUT(13:23)
+
+	   CALL WRITEDIR(0,IER)
+	   IF (REMOTE_SET.EQ.4) THEN
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+              CALL GET_MSGKEY(NEWEST_EXBTIM,NEWS_F_EXPIRED_DATE)
+	      CALL REWRITE_FOLDER_FILE(IER)
+	      CALL CLOSE_BULLNEWS 
+	   END IF
+	ELSE IF (BULL_DELETE.EQ.EBULL) THEN
+	   IF (REMOTE_SET.NE.4) CALL CLEANUP_DIRFILE(SBULL)
+				! Reorder directory file
+
+	   CALL UPDATE_ALWAYS	! Somewhat a kludgey way of updating latest
+				! bulletin and expired dates.
+
+	   IF (REMOTE_SET.NE.4.AND.SBULL.LE.BULL_POINT) THEN
+	      IF (BULL_POINT.GT.EBULL) THEN
+	         BULL_POINT = BULL_POINT - (EBULL - SBULL + 1)
+	      ELSE
+		 BULL_POINT = SBULL - 1
+	      END IF
+	   END IF		! Readjust where which bulletin to read next
+				! if deletion causes messages to be moved.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_2_VALS(INPUT,ILEN,SVAL,EVAL,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*(*) INPUT
+
+	DELIM = MAX(INDEX(INPUT,':'),INDEX(INPUT,'-'))
+
+	IF (DELIM.EQ.0) THEN
+	   DECODE(ILEN,'(I<ILEN>)',INPUT,IOSTAT=IER) SVAL
+	   EVAL = SVAL
+	ELSE
+	   DECODE(DELIM-1,'(I<DELIM-1>)',INPUT,IOSTAT=IER) SVAL
+	   CALL STR$UPCASE(INPUT,INPUT)
+	   IF (IER.NE.0) THEN
+	      IF (INDEX('CURRENT',INPUT(:DELIM-1)).EQ.1) THEN
+		 SVAL = BULL_POINT
+		 IER = 0
+	      END IF
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      ILEN = ILEN - DELIM
+	      DECODE(ILEN,'(I<ILEN>)',INPUT(DELIM+1:),IOSTAT=IER) EVAL
+	      IF (IER.NE.0) THEN
+	         IF (INDEX('LAST',INPUT(DELIM+1:TRIM(INPUT))).EQ.1) THEN
+		    EVAL = F_NBULL
+		    IER = 0
+                 ELSE IF (INDEX('CURRENT',
+     &                  INPUT(DELIM+1:TRIM(INPUT))).EQ.1) THEN
+                    EVAL = BULL_POINT
+                    IER = 0
+                 END IF
+ 	      END IF
+	   END IF
+	   IF (EVAL.LT.SVAL) IER = 2
+	END IF
+
+	RETURN
+	END
+
+ 
+
+	SUBROUTINE DIRECTORY(DIR_COUNT)
+C
+C  SUBROUTINE DIRECTORY
+C
+C  FUNCTION: Display directory of messages.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	DATA SCRATCH_D1/0/
+	DATA EXCLUDE_D1/0/
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /CLOSE_FILES_INFO/ CLOSED_FILES
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /POST/ POSTTIME
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /NEW_DIR/ NEW
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /DIRMODE/ DIRMODE
+	DATA DIRMODE/.FALSE./
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED,CLI$_PRESENT,CLOSE_FILES
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER DATETIME*24,SEARCH_STRING*80,OUTLINE*80
+        CHARACTER GROUP*80,STAT*4
+
+	INTEGER TODAY(2)
+
+	CHARACTER*12 EXPIRES,DIR_TYPE
+
+        INTEGER TIMADR(2)                       ! Buffer containing time
+
+	DATA WAITEFN /0/
+
+	NEXT = .TRUE.
+	DIRMODE = .TRUE.
+
+	CALL INIT_QUEUE(SCRATCH_F1,GROUP)
+
+	IF (WAITEFN.EQ.0) CALL LIB$GET_EF(WAITEFN)
+        IER=SYS$BINTIM('0 00:00:05.00',TIMADR)
+   
+	KILL = BTEST(BULL_USER_CUSTOM,1).AND.BTEST(BULL_USER_CUSTOM,3)
+	IF (KILL) IER1 = 0
+
+	FOUND = 0
+	OUT = 6
+
+	CONT = .FALSE.
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   CONT = CLI$PRESENT('CONTINUE')
+	ELSE IF (INCMD(:3).EQ.'   '.AND.NFOLDER.LT.0) THEN
+	   CONT = .TRUE.
+	END IF
+	IF (CONT) THEN
+	   CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+	   SUBJECT = SUBJECT1
+	   REPLY = REPLY1
+	   SEARCH = SEARCH1
+	   FROM_SEARCH = FROM_SEARCH1
+	   SINCE = SINCE1
+	   NEW = NEW1
+           ANY_SEARCH = SUBJECT.OR.REPLY.OR.SEARCH.OR.FROM_SEARCH
+	   IF (.NOT.ANY_SEARCH) THEN 
+	      WRITE (6,'('' ERROR: No previous search to continue.'')')
+	      RETURN
+	   END IF
+	   INCMD = ' '
+	   LEN_P = 0
+	   DIR_COUNT = DIR_COUNT1
+	   NFOLDER = NFOLDER1
+	   I = DIR_COUNT
+	   IF (DIR_COUNT.EQ.-1) THEN 
+	      I = SBULL - 1
+	   END IF
+	   GO TO 200
+	END IF
+	NFOLDER = 0
+
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   IF (CLI$GET_VALUE('OUTPUT',BULL_PARAMETER,LEN_P)) THEN
+	      OPEN(UNIT=3,FILE=BULL_PARAMETER(:LEN_P),IOSTAT=IER,
+     &		DEFAULTFILE='.LIS',
+     &	        RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      IF (IER.NE.0) THEN
+	         WRITE(6,1000) BULL_PARAMETER(:LEN_P)
+		 RETURN
+	      END IF
+	      OUT = 3
+	      INQUIRE (UNIT=3,NAME=BULL_PARAMETER)
+	      WRITE (6,1040) BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+	   ELSE
+	      CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+	   END IF
+	   IF (.NOT.CLI$PRESENT('SELECT_FOLDER')) THEN
+	      IF (CLI$PRESENT('MARKED')) THEN
+		 READ_TAG = 1 + IBSET(0,1)
+	      ELSE IF (CLI$PRESENT('SEEN')) THEN
+		 READ_TAG = 1 + IBSET(0,2)
+	      ELSE IF (CLI$PRESENT('UNMARKED')) THEN
+		 READ_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+	      ELSE IF (CLI$PRESENT('UNSEEN')) THEN
+		 READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+	      ELSE IF (CLI$PRESENT('ALL')) THEN
+		 READ_TAG = IBSET(0,1) + IBSET(0,2)
+		 IF (REMOTE_SET.GE.3) THEN
+		    BULL_POINT = F_START - 1
+		 ELSE
+		    BULL_POINT = 0
+		 END IF
+ 	      END IF
+	      IF (READ_TAG) THEN
+	         IF (.NOT.(FOLDER_NUMBER.GE.0.OR.REMOTE_SET.GE.3)) THEN
+		    WRITE (6,'('' ERROR: Invalid qualifier'',
+     &			       '' with remote folder.'')')
+		    READ_TAG = IBSET(0,1) + IBSET(0,2)
+		    GO TO 9999
+		 END IF
+		 CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,BULL_POINT)
+	      END IF
+	   END IF
+	   SUBJECT = CLI$PRESENT('SUBJECT').OR.CLI$PRESENT('NOREPLIES')
+	   REPLY = CLI$PRESENT('REPLY')
+           REPLY_FIRST = REPLY
+	   SEARCH = CLI$PRESENT('SEARCH')
+	   FROM_SEARCH = CLI$PRESENT('FROM')
+           ANY_SEARCH = SUBJECT.OR.REPLY.OR.SEARCH.OR.FROM_SEARCH
+	   EXTRACTING = CLI$PRESENT('EXTRACT')
+	   PRINTING = CLI$PRESENT('PRINT')
+	   POSTTIME = CLI$PRESENT('POST')
+	   NEW = CLI$PRESENT('NEW')
+	   NEGATED = CLI$PRESENT('NEGATED')
+	   IF (SEARCH) THEN
+	      IER1 = CLI$GET_VALUE('SEARCH',SEARCH_STRING,SLEN)
+	   ELSE IF (SUBJECT) THEN
+	      IER1 = CLI$GET_VALUE('SUBJECT',SEARCH_STRING,SLEN)
+           ELSE IF (FROM_SEARCH) THEN
+              IER1 = CLI$GET_VALUE('FROM',SEARCH_STRING,SLEN)
+	   ELSE IF (REPLY) THEN
+	      SEARCH_STRING = ' '
+	   ELSE IF (CLI$PRESENT('NOREPLIES')) THEN
+	      SEARCH_STRING = 'RE:'
+	      SLEN = 3
+              NEGATED = .TRUE.
+	   END IF
+
+	   MATCH_MODE = 0
+	   IF (CLI$PRESENT('MATCH')) THEN
+	      CALL CLI$GET_VALUE('MATCH',BULL_PARAMETER,LEN_P)
+	      IF (BULL_PARAMETER(:LEN_P).EQ.'AND') MATCH_MODE = 1
+	      IF (BULL_PARAMETER(:LEN_P).EQ.'XOR') MATCH_MODE = 2
+	   END IF
+	ELSE
+	   CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+	   EXTRACTING = .FALSE.
+	   PRINTING = .FALSE.
+	   POSTTIME = .TRUE.
+	   IF (INCMD(:3).EQ.'IND') THEN
+	      SUBJECT = .FALSE.
+	      REPLY = .FALSE.
+              REPLY_FIRST = .FALSE.
+	      SEARCH = .FALSE.
+	      FROM_SEARCH = .FALSE.
+              ANY_SEARCH = .FALSE.
+	   ELSE
+	      NEW = .FALSE.
+	   END IF
+	END IF
+	OUTPUT = EXTRACTING.OR.PRINTING
+
+	START = .FALSE.
+	SINCE = .FALSE.
+	IF (INCMD(:3).EQ.'DIR') THEN
+	   IF (CLI$PRESENT('GROUP')) THEN
+	      CALL INIT_QUEUE(SCRATCH_F1,GROUP)
+	      SCRATCH_F = SCRATCH_F1
+	      NGROUP = 0
+	      DO WHILE (CLI$GET_VALUE('GROUP',GROUP)
+     &	       .NE.%LOC(CLI$_ABSENT))	   	   ! Get the specified folders
+	         NGROUP = NGROUP + 1
+	         CALL LOWERCASE(GROUP)
+	         CALL WRITE_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	      END DO
+	      SCRATCH_F = SCRATCH_F1
+	      CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	      GLEN = TRIM(GROUP)
+	      FEEDBACK = CLI$PRESENT('FEEDBACK')
+	      NFOLDER = -1000
+	      NFOLDER1 = -1000
+	      SUBJECT1 = SUBJECT
+	      REPLY1 = REPLY
+	      SEARCH1 = SEARCH
+	      FROM_SEARCH1 = FROM_SEARCH
+	      I = SBULL - 1
+	      SINCE = CLI$PRESENT('SINCE')
+	      IF (SINCE) IER = CLI$GET_VALUE('SINCE',DATETIME)
+	      SINCE1 = SINCE
+	      NEW1 = NEW
+	      GOTO 200
+	   END IF
+	END IF
+
+C
+C  Directory listing is first buffered into temporary memory storage before
+C  being outputted to the terminal.  This is to be able to quickly close the
+C  directory file, and to avoid the possibility of the user holding the screen,
+C  and thus causing the directory file to stay open.  The temporary memory
+C  is structured as a linked-list queue, where SCRATCH_D1 points to the header
+C  of the queue.  See BULLSUBS.FOR for more description of the queue.
+C
+
+	CALL INIT_QUEUE(SCRATCH_D1,BULLDIR_ENTRY)
+	SCRATCH_D = SCRATCH_D1
+	CALL INIT_QUEUE(EXCLUDE_D1,%DESCR(I))
+	EXCLUDE_D = EXCLUDE_D1
+	NEXCLUDE = 0
+
+	CALL OPEN_BULLDIR_SHARED		! Get directory file
+
+	CALL READDIR(0,IER)			! Does directory header exist?
+	NEWDIR = .FALSE.
+	IF (IER.EQ.1.AND.NBULL.GT.0) THEN	! And are there messages?
+	   IF (DIR_COUNT.EQ.0) THEN
+	      NEWDIR = .TRUE.
+	      EXPIRATION = CLI$PRESENT('EXPIRATION')
+	      IF (CLI$PRESENT('START')) THEN	! Start number specified?
+		 START = .TRUE.
+	         IER = CLI$GET_VALUE('START',BULL_PARAMETER,LEN_P)
+	         DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) DIR_COUNT
+		 IF (DIR_COUNT.LT.1) THEN
+		    WRITE (6,'('' ERROR: Invalid starting message.'')')
+		    CALL CLOSE_BULLDIR
+		    DIR_COUNT = 0
+		    GO TO 9999
+		 END IF
+	      ELSE IF (CLI$PRESENT('SINCE').OR.NEW) THEN
+		 SINCE = CLI$PRESENT('SINCE')
+	         IF (SINCE) IER = CLI$GET_VALUE('SINCE',DATETIME)
+		 CALL GET_NEW_OR_SINCE(NEW,SINCE,IER,DATETIME)
+		 IF (NEW.AND.IER.EQ.0) THEN	! was /NEW specified?
+		    IF (REMOTE_SET.LT.3) THEN
+		       WRITE (6,'('' No new messages are present in'',
+     &			'' folder '',A,''.'')') FOLDER(:TRIM(FOLDER))
+		       CALL CLOSE_BULLDIR
+		       GO TO 9999
+		    ELSE
+		       WRITE (6,'('' No new messages are present in'',
+     &			 '' folder '',A,''.'')')
+     &			 FOLDER_NAME(:TRIM(FOLDER_NAME))
+		       CALL CLOSE_BULLDIR
+		       GO TO 9999
+		    END IF
+		 END IF
+
+		 IF (IER.EQ.0) THEN
+		    WRITE (6,'('' No messages past specified date.'')')
+		    CALL CLOSE_BULLDIR
+		    GO TO 9999
+		 ELSE
+		    DIR_COUNT = IER
+		 END IF
+	      ELSE
+	         DIR_COUNT = BULL_POINT
+		 IF (DIR_COUNT.EQ.0) DIR_COUNT = 1
+	      END IF
+
+	      IER1 = 0
+
+	      IF (READ_TAG) THEN
+	         IF (SUBJECT.OR.REPLY.OR.SEARCH.OR.FROM_SEARCH) THEN
+		    WRITE (6,'('' ERROR: Qualifier not valid when '',
+     &			''displaying only tagged messages.'')')
+	            SUBJECT = .FALSE.
+	            REPLY = .FALSE.
+	      	    SEARCH = .FALSE.
+	      	    FROM_SEARCH = .FALSE.
+	      	    ANY_SEARCH = .FALSE.
+		    CALL CLOSE_BULLDIR
+		    GO TO 9999
+		 END IF
+	         IF (.NOT.(SINCE.OR.NEW.OR.START)) THEN
+	            DIR_COUNT = 1
+		 END IF
+		 CALL READDIR(DIR_COUNT,IER1)
+		 IF (IER1.EQ.DIR_COUNT+1) IER1 = 0
+		 IF (REMOTE_SET.GE.3.OR.BTEST(READ_TAG,3)) THEN
+		    MSG_NUM = DIR_COUNT-1
+		 ELSE
+		    CALL DECREMENT_MSG_KEY
+	         END IF
+	      END IF
+
+	      IF (START.AND.DIR_COUNT.GT.NBULL) THEN
+	         IF (READ_TAG) THEN
+		    SBULL = NBULL + 1
+		    GO TO 100
+		 ELSE
+		    START = .FALSE.
+		    DIR_COUNT = NBULL
+		 END IF
+	      END IF
+	      IF (SINCE.OR.NEW.OR.START) THEN
+		 SBULL = DIR_COUNT
+	         EBULL = DIR_COUNT + (PAGE_LENGTH - 7) - 1
+	         IF (EBULL.GE.NBULL-2) EBULL = NBULL
+	      ELSE
+		 DIFF = 1
+	         IF (REMOTE_SET.LT.3.AND.DIR_COUNT.NE.NBULL) THEN
+		    CALL READDIR(DIR_COUNT,IER)
+	   	    DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,
+     &			       FOLDER_NUMBER+1),MSG_BTIM)
+	            IF (LAST_READ_BTIM(1,FOLDER_NUMBER+1).EQ.MSG_BTIM(1)
+     &		   .AND.LAST_READ_BTIM(2,FOLDER_NUMBER+1).EQ.MSG_BTIM(2))
+     &			DIFF = 0
+		    IF (READ_TAG) CALL DECREMENT_MSG_KEY
+	         ELSE IF (DIR_COUNT.NE.F_NBULL) THEN
+		    CALL NEWS_GET_NEWEST_MESSAGE(DIFF)
+		    IF (DIFF.NE.0) THEN
+		       DIFF = DIFF - DIR_COUNT - 1
+	            ELSE
+	               DIFF = 1
+	            END IF
+                 END IF
+	         IF (DIFF.GT.0.AND.
+     &		     NBULL-DIR_COUNT+1.LE.PAGE_LENGTH-5) THEN
+	            EBULL = NBULL
+	            SBULL = NBULL - (PAGE_LENGTH-5) + 1
+	            IF (SBULL.LT.1) SBULL = 1
+	         ELSE
+	            SBULL = DIR_COUNT
+	            EBULL = DIR_COUNT + (PAGE_LENGTH - 7) - 1
+	            IF (EBULL.GE.NBULL-2) EBULL = NBULL
+	         END IF
+	      END IF
+
+	      IER1 = 0
+	      IF (REMOTE_SET.LT.3) F_START = 1
+	      IF (DIR_COUNT.GT.F_START.AND.KILL.AND..NOT.(ANY_SEARCH.OR.START
+     &		 .OR.SINCE.OR.NEW).AND.NEWDIR.AND..NOT.READ_TAG) THEN
+       	         IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	         I = DIR_COUNT
+		 NUM = 0
+	         SBULL = DIR_COUNT
+	 	 DO WHILE (NUM.LT.PAGE_LENGTH-5.AND.I.LE.NBULL)
+		    CALL READDIR(I,IER)
+		    IF (I.EQ.NBULL) IER1 = 1
+		    IF (I.EQ.DIR_COUNT.AND.I+1.NE.IER) DIR_COUNT = I + 1
+		    IF (I+1.EQ.IER) THEN 
+		       NUM = NUM + 1
+	               IF (BTEST(SYSTEM,8)) THEN
+	                  CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		          NEXCLUDE = NEXCLUDE + 1
+		       END IF
+		    ELSE
+	               CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(I))
+		       NEXCLUDE = NEXCLUDE + 1
+		    END IF
+		    I = I + 1
+		 END DO
+		 IF (IER1.EQ.0.AND.NUM.GT.PAGE_LENGTH-7) NUM = PAGE_LENGTH - 7
+	         IF (IER1.NE.0.AND.NUM.LT.PAGE_LENGTH-5.AND.
+     &				SBULL.GT.F_START) THEN
+	            I = SBULL - 1
+		    NEXT = .FALSE.
+	 	    DO WHILE (NUM.LT.PAGE_LENGTH-5.AND.I.GE.F_START)
+		       CALL READDIR(I,IER)
+		       IF (I.EQ.NBULL) IER1 = 1
+		       IF (I+1.EQ.IER) THEN
+			  NUM = NUM + 1
+		          DIR_COUNT = I
+	                  IF (BTEST(SYSTEM,8)) THEN
+	                     CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		             NEXCLUDE = NEXCLUDE + 1
+		          END IF
+		       ELSE
+	                  CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &					%DESCR(I))
+		          NEXCLUDE = NEXCLUDE + 1
+		       END IF
+		       I = I - 1
+		    END DO
+		    NEXT = .TRUE.
+	         END IF
+	         SBULL = DIR_COUNT
+	         EBULL = SBULL + NUM - 1
+	      END IF
+	   ELSE IF (DIR_COUNT.EQ.-1.AND..NOT.READ_TAG) THEN
+	      SUBJECT = .FALSE.
+	      REPLY = .FALSE.
+              SEARCH = .FALSE.
+              FROM_SEARCH = .FALSE.
+	      SBULL = (SBULL - 1) - ((PAGE_LENGTH - 7) - 1)
+	      IF (SBULL.LT.1) SBULL = 1
+	      EBULL = SBULL + (PAGE_LENGTH - 7) - 1
+	      IF (NBULL-SBULL+1.LE.PAGE_LENGTH-5) THEN
+	         SBULL = NBULL - (PAGE_LENGTH-5) + 1
+	         EBULL = NBULL
+	         IF (SBULL.LT.1) SBULL = 1
+	      END IF
+	      IF ((REMOTE_SET.EQ.4.OR.KILL).AND.SBULL.GT.F_START) THEN
+	         NUM = EBULL - SBULL + 1
+	         I = EBULL
+	         NEXT = .FALSE.
+		 NUM1 = 0
+		 EBULL = 0
+	 	 DO WHILE (NUM.GT.0.AND.I.GE.F_START)
+		    CALL READDIR(I,IER)
+		    IF (I.EQ.NBULL) IER1 = 1
+		    IF (I+1.EQ.IER) THEN
+		       IF (EBULL.EQ.0) EBULL = I
+		       NUM = NUM - 1
+		       NUM1 = NUM1 + 1
+		       SBULL = I
+	               IF (BTEST(SYSTEM,8)) THEN
+	                  CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		          NEXCLUDE = NEXCLUDE + 1
+		       END IF
+		    ELSE
+	               CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(I))
+		       NEXCLUDE = NEXCLUDE + 1
+	            END IF
+		    IF (NUM.GT.0) I = I - 1
+		 END DO
+       	         IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	         NEXT = .TRUE.
+		 NUM = NUM1
+	         IF (NUM.LE.PAGE_LENGTH-7) THEN
+	            IF (IER1.EQ.0.AND.I.LE.F_START) THEN
+		       I = EBULL
+	               DO WHILE (I.LT.NBULL.AND.NUM.LE.PAGE_LENGTH-5)
+	                  I = I + 1
+	                  CALL READDIR(I,IER)
+			  IF (I+1.EQ.IER) THEN
+			     NUM = NUM + 1 
+	               	     IF (BTEST(SYSTEM,8)) THEN
+	                        CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		                NEXCLUDE = NEXCLUDE + 1
+		             END IF
+			  ELSE
+	                     CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(I))
+		             NEXCLUDE = NEXCLUDE + 1
+		          END IF
+	               END DO
+	               IF (NUM.GT.PAGE_LENGTH-5) NUM = PAGE_LENGTH-7
+                    ELSE IF (IER1.NE.0.AND.I.GT.F_START) THEN
+		       I = F_START - 1
+		       J = 0
+	               DO WHILE (J.LT.3.AND.I.LT.NBULL)
+	                  I = I + 1
+	                  CALL READDIR(I,IER)
+			  IF (I+1.EQ.IER) THEN
+			     J = J + 1
+	                     IF (BTEST(SYSTEM,8)) THEN
+	                        CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(-I))
+		                NEXCLUDE = NEXCLUDE + 1
+		             END IF
+			  ELSE
+	                     CALL WRITE_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,
+     &						%DESCR(I))
+		             NEXCLUDE = NEXCLUDE + 1
+		          END IF
+	               END DO
+	               IF (MSG_NUM.GE.SBULL) THEN 
+			  NUM = NUM + 2 
+	                  SBULL = F_START
+	               END IF
+	            END IF
+	         END IF
+	         EBULL = SBULL + NUM - 1
+	      END IF
+	   ELSE IF (DIR_COUNT.EQ.-1.AND.READ_TAG) THEN
+100	      CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,FIRST_BULL)
+	      FIRST_BULL = FIRST_BULL + 1
+	      DIR_COUNT = FIRST_BULL
+	      IER1 = IER
+	      IER = 0
+	      FBULL = 0
+	      EBULL = 0
+	      LBULL = SBULL.GT.NBULL
+	      DO WHILE (SBULL.GT.FIRST_BULL.AND.IER.EQ.0)
+		 SBULL = SBULL - 1
+	         CALL READDIR(SBULL,IER)
+		 IF (IER.EQ.SBULL+1) THEN
+	            CALL GET_THIS_TAG(FOLDER_NUMBER,IER,DIR_COUNT,DUMMY)
+		    IF (IER.EQ.0) THEN
+		       IF (FBULL.EQ.0) EBULL = DIR_COUNT
+		       FBULL = FBULL +1
+		       IF ((.NOT.LBULL.AND.FBULL.EQ.PAGE_LENGTH-7).OR.
+     &			   (LBULL.AND.FBULL.EQ.PAGE_LENGTH-5)) THEN
+		          IER = 1
+		       END IF
+		    ELSE
+		       IER = 0
+		    END IF
+		 ELSE
+		    IER = 1
+		 END IF
+	      END DO
+	      IF (DIR_COUNT.EQ.FIRST_BULL.AND..NOT.LBULL) THEN
+		 CALL READDIR(EBULL,IER)
+		 IER = 0
+		 DO WHILE (IER.EQ.0.AND.FBULL.LT.PAGE_LENGTH-7)
+		    CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DIR_COUNT,DUMMY)
+		    IF (IER.EQ.0) THEN
+		       FBULL = FBULL + 1
+		       EBULL = DIR_COUNT
+		    END IF
+		 END DO
+		 DO I=1,3
+		    CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DIR_COUNT,DUMMY)
+		 END DO
+		 IF (IER.NE.0) THEN
+		    EBULL = DIR_COUNT
+		    FBULL = FBULL + 2
+	         END IF
+	      END IF
+	      CALL READDIR(EBULL,IER)
+	      IF (EBULL+1.NE.IER) THEN
+		 EBULL = EBULL + 1
+	      ELSE
+	         CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DUMMY,DUMMY1)
+		 IF (IER.NE.0) EBULL = EBULL + 1
+	      END IF
+	      CALL READDIR(SBULL,IER)
+	      IF (REMOTE_SET.GE.3.OR.BTEST(READ_TAG,3)) THEN
+		 MSG_NUM = MSG_NUM-1
+	      ELSE
+		 CALL DECREMENT_MSG_KEY
+	      END IF
+	      EBULL = SBULL + FBULL - 1
+	   ELSE
+	      SBULL = DIR_COUNT
+	      EBULL = DIR_COUNT + (PAGE_LENGTH - 7) - 1
+	      IF (EBULL.GE.NBULL-2) EBULL = NBULL
+	   END IF
+	   IF (.NOT.PAGING.OR.OUTPUT.OR.OUT.EQ.3) EBULL = NBULL
+	   IF (INCMD(:3).EQ.'DIR') THEN
+	      IF (CLI$GET_VALUE('END',BULL_PARAMETER,LEN_P)) THEN
+	         DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) EBULL
+	         EBULL = MIN(EBULL,NBULL)
+	      END IF
+	   END IF
+	   IF (ANY_SEARCH) THEN
+       	      IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	   ELSE IF ((.NOT.REMOTE_SET.OR.KILL).AND..NOT.READ_TAG) THEN
+       	      IF (REMOTE_SET.EQ.3) NEWGROUP = .TRUE.
+	      EXCLUDE_D = EXCLUDE_D1
+	      SEXC = NBULL + 1
+	      LEXC = 0
+	      DO I=1,NEXCLUDE
+	         CALL READ_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(J))
+		 IF (J.LT.SEXC) SEXC = J
+		 IF (J.GT.LEXC) LEXC = J
+	      END DO
+	      I1 = SBULL
+	      I = SBULL
+	      DO WHILE (I.LE.EBULL)
+	         EXCLUDE_D = EXCLUDE_D1
+		 J = 0
+		 IER = I1
+		 IF (I1.GE.SEXC.AND.I1.LE.LEXC) THEN 
+		    N = NEXCLUDE
+		    DO WHILE (N.GT.0.AND.J.EQ.0)
+	               CALL READ_QUEUE(%VAL(EXCLUDE_D),EXCLUDE_D,%DESCR(J))
+		       N = N - 1
+		       IF (J.NE.I1.AND.J.NE.-I1) J = 0
+		    END DO
+	            IF (J.LE.0) THEN 
+	               BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,1)
+		       CALL READDIR(I1,IER)
+	               BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+		       IF (J.LT.0) SYSTEM = IBSET(SYSTEM,8)
+		    END IF
+	         ELSE
+	            CALL READDIR(I1,IER)
+		 END IF
+		 IF (KILL.AND.I1.EQ.NBULL) IER1 = 1
+		 IF (IER.EQ.I1+1) THEN
+	            CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,
+     &					BULLDIR_ENTRY)
+		    I = I + 1
+	         ELSE IF (I1.GE.NBULL) THEN
+		    EBULL = I - 1
+	         END IF
+	         I1 = I1 + 1
+	      END DO
+	   ELSE IF (READ_TAG) THEN
+	      I = 0
+	      DO WHILE (I.LE.EBULL.AND.IER1.EQ.0)
+		 CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,DIR_COUNT,TAG_TYPE)
+		 IF (I.EQ.0.AND.IER1.EQ.0) THEN
+		    EBULL = EBULL - SBULL + DIR_COUNT
+		    SBULL = DIR_COUNT
+		    I = SBULL
+		 END IF
+	 	 SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+	         CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+		 I = I + 1
+	      END DO
+	      EBULL = I - 1
+	      IF (IER1.NE.0) THEN
+	         EBULL = EBULL - 1
+	      ELSE
+	         CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,DUMMY,TAG_TYPE)
+		 IF (IER1.EQ.0) THEN
+		    IER = 0
+		    EBULL_SAVE = EBULL
+		    DO I=1,2
+		       IF (IER.EQ.0) THEN
+			  SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+	                  CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,
+     &							BULLDIR_ENTRY)
+			  EBULL = EBULL + 1
+	                  CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,DUMMY,
+     &				TAG_TYPE)
+		       END IF
+		    END DO
+		    IF (IER.NE.0) THEN
+	               CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,FIRST_BULL)
+	               IF (SBULL.NE.FIRST_BULL+1) EBULL = EBULL_SAVE
+		       IER1 = 1
+		    ELSE
+		       EBULL = EBULL_SAVE
+		    END IF
+		 END IF
+	      END IF
+	   ELSE
+	      CALL REMOTE_DIRECTORY_COMMAND
+     &				     (SBULL,EBULL,.FALSE.,SCRATCH_D,IER)
+	      IF (IER.NE.0) THEN
+	         CALL CLOSE_BULLDIR
+		 CALL DISCONNECT_REMOTE
+		 GO TO 9999
+	      END IF
+	   END IF
+	ELSE
+	   NBULL = 0
+	END IF
+
+	IF (NBULL.EQ.0.OR.EBULL.LT.SBULL) THEN
+	   CALL CLOSE_BULLDIR			! We don't need file anymore
+	   IF (READ_TAG) THEN
+	      IF (BTEST(READ_TAG,1).AND.BTEST(READ_TAG,3)) THEN
+		 DIR_TYPE = 'unmarked'
+	      ELSE IF (BTEST(READ_TAG,2).AND.BTEST(READ_TAG,3)) THEN
+		 DIR_TYPE = 'unseen'
+	      ELSE IF (BTEST(READ_TAG,1)) THEN
+		 DIR_TYPE = 'marked'
+	      ELSE IF (BTEST(READ_TAG,2)) THEN
+		 DIR_TYPE = 'seen'
+	      END IF
+	      WRITE (6,'('' No '',A,'' messages are present in'',
+     &		     '' folder '',A,''.'')')
+     &		DIR_TYPE(:TRIM(DIR_TYPE)),FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   ELSE
+	      IF (INCMD(:3).EQ.'DIR'.AND.ANY_SEARCH) THEN
+	         IF (.NOT.CLI$PRESENT('START').AND.
+     &               .NOT.CLI$PRESENT('CONT')) THEN
+	             WRITE (6,'('' No matches found starting search'',
+     &			'' from message number '',I)') SBULL
+		    DIR_COUNT = -1
+		    GO TO 9999
+	         END IF
+	      END IF
+	      WRITE (6,'('' There are no messages present.'')')
+	   END IF
+	   DIR_COUNT = -1
+	   GO TO 9999
+	END IF
+
+C
+C  Directory entries are now in queue.  Output queue entries to screen.
+C
+
+	IF (NFOLDER.EQ.0) CALL DIRECTORY_HEADER
+     &		(OUTLINE,PRINTING,EXTRACTING,EXPIRATION,OUT)
+
+	TAG = (BULL_TAG.AND.(REMOTE_SET.EQ.0.OR.REMOTE_SET.EQ.1)).OR.
+     &			(BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)
+
+	IF (.NOT.ANY_SEARCH.AND.TAG.AND..NOT.READ_TAG) THEN
+	   IF (INCMD(:3).NE.'   ') THEN
+	      SCRATCH_D = SCRATCH_D1		! Init queue pointer to header
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+	      CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,TAG_TYPE)
+	      IF (IER.NE.0) NEXT_TAG = NBULL + 1
+	   END IF
+	   SCRATCH_D = SCRATCH_D1		! Init queue pointer to header
+	   DO I=SBULL,EBULL
+	      SAVE_SCRATCH_D = SCRATCH_D
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+	      IF (TAG.AND.MSG_NUM.EQ.NEXT_TAG) THEN
+		 SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+	         CALL WRITE_QUEUE(%VAL(SAVE_SCRATCH_D),DUMMY,BULLDIR_ENTRY)
+	         CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,TAG_TYPE)
+	         IF (IER.NE.0) NEXT_TAG = NBULL + 1
+	      END IF
+	   END DO
+	END IF
+
+	CALL CLOSE_BULLDIR			! We don't need file anymore
+
+	SCRATCH_D = SCRATCH_D1			! Init queue pointer to header
+
+	I = SBULL
+	START_SEARCH = I
+	IF (.NOT.REPLY_FIRST) THEN
+	   START_SEARCH = I - 1
+	ELSE IF (.NOT.CLI$PRESENT('START')) THEN
+	   START_SEARCH = BULL_POINT
+	END IF
+200	CLOSED = .FALSE.
+	IF (ANY_SEARCH.OR.OUTPUT) THEN
+	   NUM = 0
+	   IF (NFOLDER.NE.-1000) THEN
+	      CLOSED = .TRUE.
+	      CALL OPEN_BULLDIR_SHARED
+	      IF (SEARCH.OR.OUTPUT) CALL OPEN_BULLFIL_SHARED
+	   END IF
+	   CLOSED_FILES = .FALSE.
+	   SEARCH_NUM = 1
+	   REVERSE = .FALSE.
+	END IF
+	DO WHILE (I.LE.EBULL.AND.FOUND.GT.-3)
+	   IF (.NOT.ANY_SEARCH) THEN
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,BULLDIR_ENTRY)
+	   ELSE
+ 	      IF (NFOLDER.NE.-1000.AND.I.GE.SBULL)
+     &		 CALL GET_SEARCH(FOUND,SEARCH_STRING,SEARCH_NUM,SLEN,0,
+     &		    START_SEARCH,REVERSE,SUBJECT,REPLY_FIRST,.FALSE.,
+     &		    .TRUE.,FROM_SEARCH,NEGATED,.FALSE.)
+	      IF (INCMD(:3).NE.'   '.AND.TAG.AND.FOUND.GT.0) THEN
+	         CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,
+     &		    TAG_TYPE)
+	         IF (IER.NE.0) NEXT_TAG = NBULL + 1
+		 NEXT = .FALSE.
+		 CALL READDIR(FOUND,IER)
+		 NEXT = .TRUE.
+	      END IF
+	      REPLY_FIRST = .FALSE.
+	      IF (FOUND.GT.0) THEN
+		 IF (NFOLDER.LT.0.AND.(I.EQ.F_START.OR.I.EQ.DIR_COUNT)) THEN
+	   	    IF (FEEDBACK) CALL LIB$ERASE_PAGE(1,1)
+		    CALL DIRECTORY_HEADER
+     &			(OUTLINE,PRINTING,EXTRACTING,EXPIRATION,OUT)
+		    DIR_COUNT = 0
+		    BULL_POINT = MSG_NUM - 1
+	   	    PRINT_HEADER = .TRUE.
+		 END IF
+		 SEARCH_STRING = ' '
+		 START_SEARCH = FOUND
+	         IF (TAG.AND.MSG_NUM.EQ.NEXT_TAG) THEN
+	            CALL GET_NEXT_TAG(FOLDER_NUMBER,IER,NEXT_TAG,DUMMY)
+	            IF (IER.NE.0) NEXT_TAG = NBULL + 1
+		    NEXT = .FALSE.
+		    CALL READDIR(FOUND,IER)
+		    NEXT = .TRUE.
+		    SYSTEM = SYSTEM.OR.ISHFT(TAG_TYPE,28)
+		    TAG_TYPE = DUMMY
+	         END IF
+		 IF (NFOLDER.LT.0.AND..NOT.OUTPUT) THEN 
+	            NUM = NUM + 1
+	 	    IF (NUM.EQ.PAGE_LENGTH-6) I = EBULL + 1
+		 END IF
+	      ELSE IF (NFOLDER.LT.0.AND.(OUTPUT.OR.I.LE.SBULL)) THEN
+		 IF (CLOSED) THEN
+		    IF (SEARCH.OR.OUTPUT) CALL CLOSE_BULLFIL
+		    CALL CLOSE_BULLDIR
+		    CLOSED = .FALSE.
+		 END IF
+		 GFOUND = .FALSE.
+	       	 CALL DECLARE_CTRLC_AST
+		 DO WHILE (.NOT.GFOUND.AND.NGROUP.GT.0.AND.FLAG.NE.1)
+	            CALL OPEN_BULLNEWS_SHARED
+		    CALL READ_FOLDER_FILE_KEYNUM_TEMP(-NFOLDER,IER)
+		    IF (IER.EQ.0) 
+     &		       CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+		    DO WHILE (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10))
+		       CALL READ_FOLDER_FILE_TEMP(IER)
+	            END DO
+		    IF (IER.NE.0) NFOLDER = 0
+		    DO WHILE (.NOT.GFOUND.AND.NFOLDER.NE.0.AND.FLAG.NE.1)
+	               CALL GET_NEXT_GROUP(.TRUE.,GROUP,GLEN,GFOUND,
+     &				        .FALSE.,STAT,IER,.TRUE.)
+		       CALL CLOSE_BULLFOLDER
+		       IF (GFOUND) THEN
+	      	          START_BULL = 0
+		          OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	                  FOLDER_NUMBER = -1
+		          FOLDER1 = FOLDER1_DESCRIP(
+     &		          		:INDEX(FOLDER1_DESCRIP,' '))
+	                  IF (F1_START.GT.0.AND.F1_START.LE.F1_NBULL) THEN
+			     CALL SELECT_FOLDER(.FALSE.,IER)
+			     START_SEARCH = F_START - 1
+			     IF (IER.AND.(NEW.OR.SINCE)) THEN
+				CALL OPEN_BULLDIR_SHARED
+			        CALL GET_NEW_OR_SINCE(NEW,SINCE,IER1,DATETIME)
+			        CALL CLOSE_BULLDIR
+				IF (IER1.NE.0) THEN
+				   START_SEARCH = IER1 - 1
+				ELSE
+				   IER = 0
+				END IF
+			     END IF
+			  END IF
+		          IF (.NOT.IER.OR.F1_START.EQ.0.OR.
+     &			      F1_START.GT.F1_NBULL) THEN
+		             FOLDER_NUMBER = OLD_FOLDER_NUMBER
+		             CALL OPEN_BULLNEWS_SHARED
+			     CALL READ_FOLDER_FILE_KEYNUM_TEMP(FOLDER1_NUMBER,
+     &								IER)
+		             CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+		             GFOUND = .FALSE.
+			     IF (FLAG.EQ.1) CALL CLOSE_BULLFOLDER
+		          ELSE
+	   	             IF (FEEDBACK) WRITE (6,'('' Searching '',A)')
+     &		          		FOLDER_NAME(:TRIM(FOLDER_NAME))
+		             CHANGE = .TRUE.
+		             NFOLDER = -FOLDER_NUMBER
+			     SBULL = F_START
+			     I = SBULL - 1
+			     EBULL = F_NBULL			     
+		          END IF
+		       ELSE
+		          NFOLDER = 0
+		       END IF
+		    END DO
+		    IF (NFOLDER.EQ.0) NGROUP = NGROUP - 1
+		    IF (NFOLDER.EQ.0.AND.NGROUP.GT.0) THEN
+		       CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+		       GLEN = TRIM(GROUP)
+		       NFOLDER = -1000
+		    ELSE IF (NFOLDER.EQ.0) THEN 
+		       WRITE (6,'('' No messages found.'')')
+		    END IF
+		    IF (NFOLDER.EQ.0) I = EBULL + 1
+ 	            IF (NFOLDER.LT.-1000) THEN 
+		       CALL OPEN_BULLDIR_SHARED
+	               IF (SEARCH.OR.OUTPUT) CALL OPEN_BULLFIL_SHARED
+	               CLOSED = .TRUE.
+	            END IF
+		    NFOLDER1 = NFOLDER
+	         END DO
+		 IF (FLAG.EQ.1) THEN
+		    WRITE (6,'('' Search aborted.'')')
+		    I = EBULL + 1
+		 END IF
+	     	 CALL CANCEL_CTRLC_AST
+	      ELSE
+		 I = EBULL + 1
+	      END IF
+	      IER = SYS$SETIMR(%VAL(WAITEFN),TIMADR,CLOSE_FILES,)
+	   END IF
+	   IF (I.GE.SBULL.AND.I.LE.EBULL.AND.NFOLDER.NE.-1000) THEN
+	      CALL CONVERT_ENTRY_FROMBIN_FOLDER
+	      IF (BTEST(SYSTEM,30)) THEN
+		 OUTLINE  = '>'
+	      ELSE IF (BTEST(SYSTEM,8)) THEN
+		 OUTLINE  = '#'
+	      ELSE
+		 OUTLINE  = ' '
+	      END IF
+	      IF (BTEST(SYSTEM,29)) THEN
+		 OUTLINE(2:)  = '*'
+	      ELSE
+		 OUTLINE(2:)  = ' '
+	      END IF
+	      N = MAX(INT(LOG10(REAL(MSG_NUM)))+1,3)
+	      IF (EXDATE(8:12).LT.'1994'.AND.REMOTE_SET.NE.3) THEN
+	         WRITE(OUTLINE(3:),2010) MSG_NUM,DESCRIP(:54-N),FROM,
+     &							'(DELETED)'
+	      ELSE IF (EXPIRATION) THEN
+	         IF (BTEST(SYSTEM,2)) THEN		! Shutdown bulletin?
+		    EXPIRES = 'Shutdown'
+	         ELSE IF (BTEST(SYSTEM,1)) THEN		! Permanent bulletin?
+		    EXPIRES = 'Permanent'
+	         ELSE IF (EXDATE(8:9).EQ.'18'.AND.REMOTE_SET.EQ.3) THEN
+		    EXPIRES = 'Unknown'
+	         ELSE
+		    EXPIRES = EXDATE(:7)//EXDATE(10:11)
+	         END IF
+	         WRITE(OUTLINE(3:),2010) MSG_NUM,DESCRIP(:54-N),FROM,
+     &						EXPIRES(:9)
+	      ELSE
+	         WRITE(OUTLINE(3:),2010) MSG_NUM,DESCRIP(:54-N),FROM,
+     &						DATE(:7)//DATE(10:11)
+	      END IF
+	      NOTHING = .FALSE.
+	      IF (OUT.EQ.6) THEN 
+	         WRITE(OUT,'(1X,A)') OUTLINE
+	      ELSE
+	         WRITE(OUT,'(A)') OUTLINE
+	      END IF
+	      IF (OUTPUT) THEN
+		 FOUND_MSG = .TRUE.
+		 CALL SYS$SETAST(%VAL(0))
+		 NEXT = .FALSE.
+	         IF (PRINTING) THEN
+	            CALL PRINT(MSG_NUM,CLOSED_FILES)
+	         ELSE
+		    CALL FILE(MSG_NUM,CLOSED_FILES,PRINT_HEADER)
+	   	    PRINT_HEADER = .FALSE.
+		    IF (MSG_NUM.GT.0) THEN
+		       I = EBULL
+	               FOUND = 0
+                    ELSE
+		       MSG_NUM = -MSG_NUM
+	            END IF
+	         END IF
+		 NEXT = .TRUE.
+		 CALL SYS$SETAST(%VAL(1))
+	      END IF
+	   END IF
+	   I = I + 1
+	   IF (ANY_SEARCH) IER = SYS$CANTIM(,)
+	END DO
+
+	DIR_COUNT = MSG_NUM + 1			! Update directory counter
+
+	IF (ANY_SEARCH.OR.OUTPUT) THEN
+	   IF (CLOSED) THEN
+	      IF (SEARCH.OR.OUTPUT) CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	   END IF
+	   IF (ANY_SEARCH) THEN
+	      IF (FOUND.GT.0) THEN
+	         DIR_COUNT = FOUND + 1
+	      ELSE
+	         DIR_COUNT = NBULL + 1
+	      END IF
+	   END IF
+	END IF
+
+	IF (DIR_COUNT.GT.NBULL
+     &		.OR.((READ_TAG.OR.KILL).AND.IER1.NE.0)) THEN
+						! Outputted all entries?
+	   IF (PRINTING) THEN 
+	      IF (CLI$PRESENT('NOW').AND.FOUND_MSG) THEN
+	         INCMD = 'PRINT/NOW'
+	         IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	         CALL PRINT(MSG_NUM,CLOSED_FILES)
+	      END IF
+	   ELSE IF (EXTRACTING.AND.FOUND_MSG) THEN
+	      CALL FILE(0,CLOSED_FILES,.FALSE.)
+	   END IF
+	   IF (NFOLDER.LT.0) THEN 
+	      IF (FLAG.EQ.1) WRITE(6,1020)
+	   ELSE
+	      DIR_COUNT = -1			! Yes. Set counter to -1.
+	   END IF
+	ELSE IF (NFOLDER.NE.0.OR.(-NFOLDER1.EQ.FOLDER_NUMBER.AND.
+     &		   INCMD(:1).EQ.' ')) THEN
+	   IF (FLAG.EQ.1) WRITE(6,1020)
+	ELSE IF (FLAG.NE.1) THEN 
+	   WRITE(6,1010)			! Else say there are more
+	END IF
+
+9999	POSTTIME = .FALSE.
+	NEXT = .FALSE.
+	DIRMODE = .FALSE.
+	IF (NFOLDER.NE.0.OR.-NFOLDER1.EQ.FOLDER_NUMBER) THEN
+	   DIR_COUNT1 = DIR_COUNT
+	   IF (DIR_COUNT1.GT.NBULL) DIR_COUNT1 = -1
+	END IF
+	IF (OUT.EQ.3) CLOSE (UNIT=3)
+	RETURN
+
+1000	FORMAT(' ERROR: Error in opening file ',A,'.')
+1010	FORMAT(1X,/,' Press RETURN for more...',/)
+1020	FORMAT(1X,/,' Press RETURN for more, type SEARCH to read ',
+     &		'these messages.',/)
+1040	FORMAT(' Output being written to ',A,'.')
+
+2010	FORMAT(I<N>,1X,A<54-N>,1X,A12,1X,A9)
+
+	END
+
+
+	SUBROUTINE CLOSE_FILES
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /CLOSE_FILES_INFO/ CLOSED_FILES
+
+	INQUIRE(UNIT=1,OPENED=IER)
+	IF (IER) CALL CLOSE_BULLFIL
+
+	INQUIRE(UNIT=2,OPENED=IER)
+	IF (IER) CALL CLOSE_BULLDIR
+
+	CLOSED_FILES = .TRUE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_MSGKEY(BTIM,MSG_KEY)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER BTIM(2)
+
+	CHARACTER*8 MSG_KEY,INPUT
+
+	CALL LIB$MOVC3(8,BTIM(1),%REF(INPUT))
+
+	DO I=1,8
+	   MSG_KEY(I:I) = INPUT(9-I:9-I)
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE FILE(FILE_NUM,OPEN_IT,PRINT_HEADER)
+C
+C  SUBROUTINE FILE
+C
+C  FUNCTION:  Copies a bulletin to a file.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /READ_DISPLAY/ LINE_OFFSET
+
+	COMMON /FILE_DIRECTORY/ FILE_DIRECTORY
+	CHARACTER*64 FILE_DIRECTORY
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER*128 FILENAME
+
+	DATA OPENED /.FALSE./
+
+	IF (CAPTIVE(1)) THEN
+	   WRITE (6,'('' ERROR: Command invalid from CAPTIVE account.'')')
+	   RETURN
+	END IF
+
+10	IF (FILE_NUM.EQ.0) THEN
+	IF (.NOT.OPEN_IT) THEN
+	   OPENED = .FALSE.
+	   CLOSE (UNIT=3)
+	   RETURN
+	END IF
+	IF (OPENED) THEN
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	   CLOSE (UNIT=3)			! Bulletin copy completed
+	   OPENED = .FALSE.
+	   RETURN
+	END IF
+	IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	   CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+	   IF (EBULL.GT.F_NBULL) EBULL = F_NBULL
+	ELSE IF (CLI$PRESENT('ALL')) THEN
+	   SBULL = 1
+	   EBULL = F_NBULL
+	   IER = 0
+	ELSE IF (BULL_POINT.EQ.0) THEN	! No.  Have we just read a bulletin?
+	   WRITE(6,1010)		! No, then error.
+	   RETURN
+	ELSE
+	   SBULL = BULL_POINT
+	   EBULL = SBULL
+	   IER = 0
+	END IF
+
+	IF (SBULL.LE.0.OR.IER.NE.0.OR.EBULL.LT.SBULL) THEN
+	   WRITE (6,1015)
+	   IF (OPENED) THEN
+	      CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	      CLOSE (UNIT=3)			! Bulletin copy completed
+	      OPENED = .FALSE.
+	   END IF
+	   WRITE (6,'(1X,A)') BULL_PARAMETER(:LEN_P)
+	   RETURN
+	END IF
+	ELSE
+	   SBULL = FILE_NUM
+	   EBULL = SBULL
+	END IF
+
+	IF (.NOT.OPENED) THEN
+	   IER = CLI$GET_VALUE('EXTRACT',FILENAME,LEN_F)
+
+	   IF (.NOT.IER) THEN
+	      FILENAME = FOLDER
+	      DO I=1,LEN(FILENAME)
+	         IF (FILENAME(I:I).EQ.'.') FILENAME(I:I) = '_'
+	      END DO
+	      FILENAME = FILENAME(:TRIM(FILENAME))//'.TXT'
+	      LEN_F = TRIM(FILENAME)
+	   END IF
+
+	   IF (TRIM(FILE_DIRECTORY).GT.0.AND.INDEX(FILENAME,':').EQ.0
+     &	       .AND.INDEX(FILENAME,'[').EQ.0) THEN
+	      FILENAME = FILE_DIRECTORY(:TRIM(FILE_DIRECTORY))//FILENAME
+	      LEN_F = TRIM(FILENAME)
+	   END IF
+
+	   CALL STR$UPCASE(FILENAME,FILENAME)
+
+	   CALL DISABLE_PRIVS
+
+	   IF (CLI$PRESENT('NEW')) THEN
+	      OPEN(UNIT=3,FILE=FILENAME(:LEN_F),ERR=900,
+     &	        RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	   ELSE
+	      OPEN(UNIT=3,FILE=FILENAME(:LEN_F),IOSTAT=IER,
+     &		RECL=LINE_LENGTH,
+     &		STATUS='OLD',CARRIAGECONTROL='LIST',ACCESS='APPEND')
+	      IF (IER.NE.0) THEN
+	         OPEN(UNIT=3,FILE=FILENAME(:LEN_F),ERR=900,
+     &	           RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      ELSE IF (CLI$PRESENT('FF')) THEN
+	         WRITE (3,'(A)') CHAR(12)
+	      END IF
+	   END IF
+
+	   CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+
+	   HEAD = CLI$PRESENT('HEADER')
+
+	   IF (OPEN_IT) THEN
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL OPEN_BULLFIL_SHARED	! Open BULLETIN file
+	   END IF
+	   OPENED = .TRUE.
+	   FIRST = .TRUE.
+	END IF
+
+	IF (PRINT_HEADER) THEN
+	   WRITE (3,'(/,''Newsgroup: '',A)')
+     &		FOLDER_NAME(:TRIM(FOLDER_NAME))
+	END IF
+
+	DO FBULL = SBULL,EBULL
+	   FBULL1 = FBULL
+	   CALL READDIR(FBULL,IER)	! Get info for specified bulletin
+
+	   IF (IER.NE.FBULL+1.OR.FBULL.GT.EBULL.OR.(.NOT.CLI$PRESENT
+     &		('ALL').AND.FBULL1.EQ.SBULL.AND.FBULL.NE.SBULL)) THEN
+	      IF (REMOTE_SET.LT.3.OR.FBULL1.EQ.SBULL) WRITE(6,1030) FBULL1
+	      IF (FBULL1.GT.SBULL) GO TO 100
+	      CLOSE (UNIT=3,STATUS='DELETE')
+	      OPENED = .FALSE.
+	      IF (OPEN_IT) THEN
+	         CALL CLOSE_BULLFIL
+	         CALL CLOSE_BULLDIR
+              END IF
+	      RETURN
+	   ELSE IF (REMOTE_SET) THEN
+	      CALL REMOTE_READ_MESSAGE(FBULL,IER1)
+	      IF (IER1.GT.0) THEN
+	         CALL DISCONNECT_REMOTE
+	      ELSE
+	         CALL GET_REMOTE_MESSAGE(IER1)
+	      END IF
+	      IF (IER1.NE.0) GO TO 100
+	   END IF
+
+	   IF (.NOT.FIRST.AND.CLI$PRESENT('FF')) THEN
+	      WRITE (3,'(A)') CHAR(12)
+	   ELSE IF (FIRST) THEN
+	      FIRST = .FALSE.
+	   END IF
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (HEAD) WRITE(3,1060) INPUT(7:ILEN),DATE//' '//TIME(:8)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE IF (HEAD) THEN
+	      WRITE(3,1060) FROM,DATE//' '//TIME(:8)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      IF (HEAD) WRITE(3,1050) INPUT(7:ILEN)
+	   ELSE
+	      IF (HEAD) WRITE(3,1050) DESCRIP
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END DO
+	END DO
+
+100     IF (FILE_NUM.GT.0) THEN
+	   FILE_NUM = -FILE_NUM
+	   RETURN
+	END IF
+
+	IER = OTS$CVT_L_TI(SBULL,BULL_PARAMETER,,,)
+ 	IF (SBULL.EQ.EBULL) THEN	! Show name of file created.
+	   WRITE(6,1040)
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):),
+     &	      FILENAME(:LEN_F)
+	ELSE
+	   WRITE(6,1045)
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	   IER = OTS$CVT_L_TI(EBULL,BULL_PARAMETER,,,)
+           WRITE(6,1046)
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):),
+     &	      FILENAME(:LEN_F)
+	END IF
+
+	GO TO 10
+
+900	WRITE(6,1000) FILENAME(:LEN_F)
+	CALL ENABLE_PRIVS		! Reset BYPASS privileges
+	RETURN
+
+1000	FORMAT(' ERROR: Error in opening file ',A,'.')
+1010	FORMAT(' ERROR: You have not read any bulletin.')
+1015	FORMAT(' ERROR: Specified message number has incorrect format:')
+1030	FORMAT(' ERROR: Following bulletin was not found: ',I)
+1040	FORMAT(' Message ',A,' written to ',A)
+1045	FORMAT(' Messages ',A,'-',$)
+1046	FORMAT('+',A,' written to ',A)
+1050	FORMAT('Subj: ',A,/)
+1060	FORMAT(/,'From: ',A,/,'Date: ',A)
+
+	END
+
+
+
+	SUBROUTINE COPY2(OUT,IN)
+
+	CALL LIB$MOVC3(8,IN,OUT)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE LOGIN
+C
+C  SUBROUTINE LOGIN
+C
+C  FUNCTION: Alerts user of new messages upon logging in.
+C
+	IMPLICIT INTEGER (A - Z)
+
+        INCLUDE 'BULLFILES.INC'
+ 
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER TODAY*24,INREAD*4
+
+	DATA CTRL_G/7/
+
+	DATA GEN_DIR1/0/	! General directory link list header
+	DATA SYS_DIR1/0/	! System directory link list header
+	DATA SYS_NUM1/0/	! System message number link list header
+	DATA SYS_BUL1/0/	! System bulletin link list header
+	DATA ALL_DIR1/0/	! Full directory link list header (for remote)
+
+	DATA PAGE/0/
+
+	DATA FIRST_WRITE/.TRUE./
+	LOGICAL FIRST_WRITE
+
+	COMMON /LOGIN_BTIM/ LOGIN_BTIM_SAVE(2)
+
+	DIMENSION NOLOGIN_BTIM(2),TODAY_BTIM(2)
+	DIMENSION NEW_BTIM(2),PASSCHANGE(2),BULLCP_BTIM(2)
+	DIMENSION LOGIN_BTIM_OLD(2),LOGIN_BTIM_NEW(2)
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	FOLDER_NAME = FOLDER
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NOLOGIN_BTIM)
+	CALL SYS_BINTIM('5-NOV-1956 11:05:56',NEW_BTIM)
+
+C
+C  Find user entry in BULLUSER.DAT to update information and
+C  to get the last date that messages were read.
+C
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_HEADER(IER)		! Get the header
+
+	IF (IER.EQ.0) THEN			! Header is present.
+	   UNLOCK 4
+	   CALL READ_USER_FILE_KEYNAME(USERNAME,IER1)
+						! Find if there is an entry
+	   IF (NEW_FLAG(1).LT.143.OR.NEW_FLAG(1).GT.143) THEN
+	      NEW_FLAG(2)=0		! If old version clear GENERIC value
+	      NEW_FLAG(1)=143		! Set new version number
+	   END IF
+	   IF (IER1.EQ.0) THEN			! There is a user entry
+	      IF (COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM).GE.0) THEN
+						! DISMAIL or SET LOGIN set
+		 IF (CLI$PRESENT('ALL')) THEN
+		    CALL COPY2(LOGIN_BTIM,TODAY_BTIM(1))
+		 ELSE
+		    RETURN			! Don't notify
+	         END IF
+	      END IF
+	      CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)
+	      CALL COPY2(LOGIN_BTIM,TODAY_BTIM)
+	      REWRITE (4) USER_ENTRY
+	      IF (SYSTEM_FLAG(1).NE.0.AND.SYSTEM_FLAG(1).NE.1) READIT = 1
+	      DO I = 1,FLONG
+		 IF (SET_FLAG(I).NE.0.OR.BRIEF_FLAG(I).NE.0.OR.
+     &		    (I.GT.1.AND.SYSTEM_FLAG(I).NE.0)) READIT = 1
+	      END DO
+	   ELSE
+	      CALL CLEANUP_LOGIN		! Good time to delete dead users
+	      CALL COPY2(READ_BTIM,NEW_BTIM)	! Make new entry
+	      DO I = 1,FLONG
+	         SET_FLAG(I) = SET_FLAG_DEF(I)
+	         BRIEF_FLAG(I) = BRIEF_FLAG_DEF(I)
+		 NOTIFY_FLAG(I) = NOTIFY_FLAG_DEF(I)
+	      END DO
+	      NEW_FLAG(1) = 143
+	      NEW_FLAG(2) = 0
+	      CALL CHECK_NEWUSER(USERNAME,DISMAIL,PASSCHANGE)
+	      IF (DISMAIL.EQ.1) THEN
+		 CALL COPY2(LOGIN_BTIM,NOLOGIN_BTIM)
+	         CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)
+	      ELSE
+	         CALL COPY2(LOGIN_BTIM_SAVE,NEW_BTIM)
+		 CALL COPY2(LOGIN_BTIM,TODAY_BTIM)
+	         DO I = 1,FLONG
+		    IF (SET_FLAG(I).NE.0) READIT = 1
+	         END DO
+		 IF (COMPARE_BTIM(PASSCHANGE,NEWEST_BTIM).LT.0) IER1 = 0
+			! Old password change indicates user is new to BULLETIN
+			! but not to system, so don't limit message viewing.
+	      END IF
+	      CALL WRITE_USER_FILE(IER)
+	      IF (IER.NE.0) THEN		! Error in writing to user file
+		 WRITE (6,1070)			! Tell user of the error
+		 CALL CLOSE_BULLUSER		! Close the user file
+		 CALL EXIT			! Go away...
+	      END IF
+	      IF (DISMAIL.EQ.1) RETURN		! Go away if DISMAIL set
+	      DIFF = -1				! Force us to look at messages
+	      CALL OPEN_BULLINF_SHARED
+	      DO I=1,FOLDER_MAX
+	         CALL COPY2(LAST_READ_BTIM(1,I),READ_BTIM)
+	      END DO
+	      WRITE (9,IOSTAT=IER) USERNAME,
+     &		((LAST_READ_BTIM(I,J),I=1,2),J=1,FOLDER_MAX)
+	      CALL CLOSE_BULLINF
+	   END IF
+	   CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_SAVE)
+	   CALL READ_USER_FILE_HEADER(IER2)	! Reset read back to header
+	END IF
+
+	IF (IER.EQ.0.AND.MINUTE_DIFF(TODAY_BTIM,BBOARD_BTIM)
+     &			.GT.BBOARD_UPDATE) THEN	! Update BBOARD mail?
+	   CALL COPY2(BBOARD_BTIM,TODAY_BTIM)
+	   REWRITE (4) USER_HEADER		! Rewrite header
+	   IF (.NOT.TEST_BULLCP()) CALL CREATE_PROCESS('BBOARD')
+	ELSE IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLUSER
+	   CALL EXIT			! If no header, no messages
+	END IF
+
+	IF (IER1.EQ.0) THEN		! Skip date comparison if new entry
+C
+C  Compare and see if messages have been added since the last time
+C  that the user has logged in or used the BULLETIN facility.
+C
+	   DIFF1 = COMPARE_BTIM(LOGIN_BTIM,READ_BTIM)
+	   IF (DIFF1.LT.0) THEN		! If read messages since last login,
+	      CALL COPY2(LOGIN_BTIM,READ_BTIM)
+		! then use read date to compare with latest bulletin date
+	   END IF			! to see if should alert user.
+
+	   IF (SYSTEM_SWITCH) THEN
+	      DIFF1 = COMPARE_BTIM(SYSTEM_LOGIN_BTIM,NEWEST_BTIM)
+	   ELSE
+	      DIFF1 = COMPARE_BTIM(LOGIN_BTIM,NEWEST_BTIM)
+	   END IF
+	END IF
+
+	CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)  ! Destroyed in UPDATE_READ
+	
+	IF (NEW_FLAG(2).NE.0.AND.NEW_FLAG(2).NE.-1) THEN
+	   CALL LIB$MOVC3(4,NEW_FLAG(2),%REF(BULL_PARAMETER))
+	   CALL SUBTIME(LOGIN_BTIM,BULL_PARAMETER(:4),IER)
+	ELSE IF (DIFF1.GT.0) THEN
+	   BULL_POINT = -1
+	   IF (READIT.EQ.1) THEN
+	      CALL UPDATE_READ(1)
+	      CALL COPY2(LOGIN_BTIM_NEW,LOGIN_BTIM)
+	      CALL READ_IN_FOLDERS
+	      CALL MODIFY_SYSTEM_LIST(1)
+	   END IF
+	   CALL CLOSE_BULLUSER
+	   RETURN
+	END IF
+
+	CALL READ_IN_FOLDERS
+	CALL MODIFY_SYSTEM_LIST(1)
+        FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//FOLDER
+
+	ENTRY LOGIN_FOLDER
+
+	IF (NEW_FLAG(2).EQ.0.OR.NEW_FLAG(2).EQ.-1.OR.FOLDER_SET) THEN
+	   CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_SAVE)
+	END IF
+
+	IF (REMOTE_SET.EQ.1) THEN	! If system remote folder, use remote
+					! info, not local login time
+	   IF (LAST_SYS_BTIM(1,FOLDER_NUMBER+1).NE.0) THEN
+	    CALL COPY2(LOGIN_BTIM,LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	    LAST_SYS_BTIM(1,FOLDER_NUMBER+1) = 0
+	    LAST_SYS_BTIM(2,FOLDER_NUMBER+1) = 0
+	   ELSE
+	    DIFF1 = COMPARE_BTIM(LOGIN_BTIM,
+     &			LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	    IF (DIFF1.LT.0) THEN
+	      CALL COPY2(LOGIN_BTIM,LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	    ELSE
+	      DIFF = MINUTE_DIFF(LOGIN_BTIM,F_NEWEST_BTIM)
+	      IF (DIFF.GE.0.AND.DIFF.LE.15) THEN  ! BULLCP updates every 15 min
+	         IER = SYS$BINTIM('0 00:15',BULLCP_BTIM)
+	         BULLCP_BTIM(1) = -BULLCP_BTIM(1) ! Convert to -delta time
+	         BULLCP_BTIM(2) = -BULLCP_BTIM(2)-1
+	         CALL LIB$SUBX(LOGIN_BTIM,BULLCP_BTIM,LOGIN_BTIM)
+	      END IF
+	    END IF
+	   END IF
+	END IF
+
+	ENTRY SHOW_SYSTEM
+
+	JUST_SYSTEM = (.NOT.LOGIN_SWITCH.AND.SYSTEM_SWITCH).OR.
+     &	        (BTEST(FOLDER_FLAG,2)
+     &		.AND..NOT.TEST_SET_FLAG(FOLDER_NUMBER)
+     &		.AND..NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER))
+
+	NGEN = 0			! Number of general messages
+	NSYS = 0			! Number of system messages
+	BULL_POINT = -1
+
+	IF (IER1.NE.0.AND.FOLDER_NUMBER.GT.0) THEN
+	   IF (LOGIN_SWITCH) THEN
+	      IF (READIT.EQ.1) THEN
+	         CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM)
+	         CALL UPDATE_READ(1)
+	         CALL COPY2(LOGIN_BTIM_NEW,LOGIN_BTIM)
+	      END IF
+	      CALL CLOSE_BULLUSER
+	   END IF
+	   RETURN	! Don't overwhelm new user with lots of non-general msgs
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,2).AND.SYSTEM_SWITCH) THEN
+			! Can folder have SYSTEM messages and /SYSTEM specified?
+	   CALL COPY2(LOGIN_BTIM,SYSTEM_LOGIN_BTIM) ! Use specified login time
+						    ! for system messages.
+	END IF
+
+	IF (LOGIN_SWITCH) THEN
+	   IF (READIT.EQ.1) THEN
+	      CALL COPY2(LOGIN_BTIM_OLD,LOGIN_BTIM)
+	      CALL UPDATE_READ(1)
+	      CALL COPY2(LOGIN_BTIM_NEW,LOGIN_BTIM)
+	      CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_OLD)
+	   END IF
+	   CALL CLOSE_BULLUSER
+	END IF
+
+	IF (READIT.EQ.1.AND.FOLDER_NUMBER.GE.0.AND.REMOTE_SET.LT.3) THEN
+	   IF (LAST_SYS_BTIM(1,FOLDER_NUMBER+1).NE.0) THEN
+	      DIFF1 = COMPARE_BTIM(LOGIN_BTIM,
+     &				LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	      IF (DIFF1.LT.0) THEN
+	         CALL COPY2(LOGIN_BTIM,LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	      END IF
+	      CALL COPY2(LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &			 LOGIN_BTIM_NEW)
+	   END IF
+
+	   IF (TEST2(BRIEF_FLAG,FOLDER_NUMBER)
+     &		       .AND.TEST2(SET_FLAG,FOLDER_NUMBER)) THEN
+	      IF (.NOT.TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) GO TO 9999
+	   END IF
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED	! Get bulletin directory
+	IF (.NOT.REMOTE_SET) THEN
+	   CALL READDIR(0,IER)		! Get header info
+	ELSE
+	   NBULL = F_NBULL
+	END IF
+	   
+	CALL INIT_QUEUE(GEN_DIR1,BULLDIR_ENTRY)
+	CALL INIT_QUEUE(SYS_DIR1,BULLDIR_ENTRY)
+	CALL INIT_QUEUE(SYS_NUM1,%DESCR(ICOUNT))
+	GEN_DIR = GEN_DIR1
+	SYS_DIR = SYS_DIR1
+	SYS_NUM = SYS_NUM1
+	START = 1
+	REVERSE = 0
+	IF ((.NOT.TEST_SET_FLAG(FOLDER_NUMBER).OR.
+     &		.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER))
+     &		.AND..NOT.BTEST(FOLDER_FLAG,7)) THEN
+	   IF (REVERSE_SWITCH) REVERSE = 1
+	   IF (IER1.EQ.0) THEN
+	      CALL GET_NEWEST_MSG(LOGIN_BTIM,START)
+	      IF (START.EQ.-1) START = NBULL + 1
+	   END IF
+	END IF
+
+	IF (REMOTE_SET) THEN
+	   CALL INIT_QUEUE(ALL_DIR1,BULLDIR_ENTRY)
+	   ALL_DIR = ALL_DIR1
+	   CALL REMOTE_DIRECTORY_COMMAND(START,NBULL,
+     &					 .NOT.REVERSE,ALL_DIR,IER)
+	   IF (IER.NE.0) THEN
+	      CALL CLOSE_BULLDIR
+	      CALL DISCONNECT_REMOTE
+	      GO TO 9999
+	   END IF
+	   LAST_DIR = ALL_DIR
+	   ALL_DIR = ALL_DIR1
+	END IF
+
+	CALL GET_NODE_NUMBER(NODE_NUMBER1,NODE_AREA1)
+
+	DO ICOUNT1 = NBULL,START,-1
+	   IF (REVERSE) THEN
+	      ICOUNT = NBULL + START - ICOUNT1
+	   ELSE
+	      ICOUNT = ICOUNT1
+	   END IF
+	   IF (REMOTE_SET) THEN
+	      IF (ALL_DIR.EQ.LAST_DIR) GO TO 100
+	      CALL READ_QUEUE(%VAL(ALL_DIR),ALL_DIR,BULLDIR_ENTRY)
+	      IER = ICOUNT + 1
+	   ELSE
+	      CALL READDIR(ICOUNT,IER)
+	   END IF
+	   IF (IER1.EQ.0.AND.IER.EQ.ICOUNT+1) THEN ! Is this a totally new user?
+	      IF (.NOT.REVERSE.AND..NOT.BTEST(FOLDER_FLAG,7)) THEN 
+	         DIFF = COMPARE_BTIM(LOGIN_BTIM,MSG_BTIM) ! No, so compare date
+	         IF (DIFF.GT.0) GO TO 100
+	      END IF
+	      IGNORE = BTEST(SYSTEM,2).AND.(NODE_AREA.EQ.NODE_AREA1).AND.
+     &			(NODE_NUMBER.AND.NODE_NUMBER1)
+	      IF (.NOT.BTEST(FOLDER_FLAG,2)) SYSTEM = SYSTEM.AND.(.NOT.1)
+			! Show system msg in non-system folder as general msg
+	      IF ((USERNAME.NE.FROM.OR.SYSTEM).AND..NOT.IGNORE) THEN
+				  	! Is bulletin system or from same user?
+		 IF (SYSTEM) THEN	! Is it system bulletin? 
+		    NSYS = NSYS + 1
+		    CALL WRITE_QUEUE(%VAL(SYS_DIR),SYS_DIR,BULLDIR_ENTRY)
+		    CALL WRITE_QUEUE(%VAL(SYS_NUM),SYS_NUM,%DESCR(ICOUNT))
+	         ELSE IF (.NOT.JUST_SYSTEM) THEN
+		    IF (BTEST(FOLDER_FLAG,7)) THEN
+		       DIFF = COMPARE_BTIM
+     &			      (LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+		    ELSE IF (.NOT.SYSTEM_SWITCH) THEN
+		       DIFF = -1
+		    ELSE
+	               DIFF = COMPARE_BTIM(LOGIN_BTIM_SAVE,MSG_BTIM)
+		    END IF
+		    IF (DIFF.LT.0) THEN
+		       IF (.NOT.REVERSE.OR.BULL_POINT.EQ.-1) THEN
+		          BULL_POINT = ICOUNT - 1
+		          IF (.NOT.BTEST(FOLDER_FLAG,2).AND.
+     &			   TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &			   TEST_SET_FLAG(FOLDER_NUMBER)) GO TO 100
+		       END IF
+		       NGEN = NGEN + 1
+		       SYSTEM = ICOUNT
+		       CALL WRITE_QUEUE(%VAL(GEN_DIR),GEN_DIR,BULLDIR_ENTRY)
+		    END IF
+	         END IF
+	      END IF
+	   ELSE IF (IER.EQ.ICOUNT+1) THEN
+			! Totally new user, save only permanent system msgs
+	      IF ((SYSTEM.AND.7).EQ.3.OR.
+     &		  (SYSTEM.AND.BTEST(FOLDER_FLAG,7))) THEN
+	         NSYS = NSYS + 1
+		 CALL WRITE_QUEUE(%VAL(SYS_DIR),SYS_DIR,BULLDIR_ENTRY)
+		 CALL WRITE_QUEUE(%VAL(SYS_NUM),SYS_NUM,%DESCR(ICOUNT))
+	      ELSE IF (NGEN.EQ.0.OR.	! And save only the first non-system msg
+     &		     BTEST(FOLDER_FLAG,7)) THEN ! and SET ALWAYS folder messages
+		 SYSTEM = ICOUNT	! Save bulletin number for display
+		 IF (.NOT.REVERSE.OR.BULL_POINT.EQ.-1) THEN
+		    BULL_POINT = ICOUNT - 1
+		    IF (.NOT.BTEST(FOLDER_FLAG,2).AND.
+     &			TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &		 	TEST_SET_FLAG(FOLDER_NUMBER)) GO TO 100
+		 END IF
+		 NGEN = NGEN + 1
+		 CALL WRITE_QUEUE(%VAL(GEN_DIR),GEN_DIR,BULLDIR_ENTRY)
+	      END IF
+	   END IF
+	END DO
+100	CALL CLOSE_BULLDIR
+C
+C  Review new directory entries.  If there are system messages,
+C  copy the system bulletin into GEN_DIR file BULLSYS.SCR for outputting
+C  to the terminal.  If there are simple messages, just output the
+C  header information.
+C
+	IF (TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &			   TEST_SET_FLAG(FOLDER_NUMBER)) NGEN = 0
+
+	IF (NGEN.EQ.0.AND.NSYS.EQ.0) GO TO 9999
+
+	IF (NSYS.GT.0) THEN		! Are there any system messages?
+	   IF (FIRST_WRITE) THEN
+	      PAGE = 4		! Don't erase MAIL/PASSWORD notifies
+	      FIRST_WRITE = .FALSE.	! if this is first write to screen.
+	   END IF
+	   LENF = TRIM(FOLDER_NAME)
+	   S1 = (PAGE_WIDTH-(LENF+16))/2
+	   S2 = PAGE_WIDTH - S1 - (LENF + 16)
+	   WRITE (6,'(''+'',A,$)') CTRL_G
+	   IF (REMOTE_SET.LT.3) THEN
+	      FOLDER_NAME = FOLDER
+	   ELSE
+	      FOLDER_NAME = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	   END IF
+	   WRITE (6,1026) FOLDER_NAME(:LENF)		! Yep...
+	   PAGE = PAGE + 1
+	   CTRL_G = 0		! Don't ring bell for non-system bulls
+	   CALL OPEN_BULLFIL_SHARED
+	   CALL INIT_QUEUE(SYS_BUL1,INPUT)
+	   SYS_BUL = SYS_BUL1
+	   SYS_DIR = SYS_DIR1
+	   SYS_NUM = SYS_NUM1
+	   NSYS_LINE = 0
+	   DO J=1,NSYS
+	      CALL READ_QUEUE(%VAL(SYS_DIR),SYS_DIR,BULLDIR_ENTRY)
+	      IF (REMOTE_SET) THEN
+	         CALL READ_QUEUE(%VAL(SYS_NUM),SYS_NUM,%DESCR(ICOUNT))
+	         WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 5,ICOUNT
+	         IF (IER.GT.0) THEN
+	            CALL DISCONNECT_REMOTE
+	         ELSE
+	            CALL GET_REMOTE_MESSAGE(IER)
+	         END IF
+		 IF (IER.GT.0) THEN
+		    CALL CLOSE_BULLFIL
+		    GO TO 9999
+		 END IF
+	      END IF
+ 	      INPUT = ' '
+	      CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+	      NSYS_LINE = NSYS_LINE + 1
+	      ILEN = LINE_LENGTH + 1
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      DO WHILE (ILEN.GT.0)	! Copy bulletin to SYS_BUL link list
+		 CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+		 NSYS_LINE = NSYS_LINE + 1
+		 CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END DO
+	      IF (ILEN.LT.0) THEN
+		 CALL CLOSE_BULLFIL
+		 GO TO 9999
+	      END IF
+	      IF (J.LT.NSYS.AND.SEPARATE.NE.' ') THEN
+ 	         INPUT = ' '
+	         CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+		 DO I=1,PAGE_WIDTH
+		    INPUT(I:I) = SEPARATE
+		 END DO
+		 CALL WRITE_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+	         NSYS_LINE = NSYS_LINE + 2
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLFIL
+	   SYS_BUL = SYS_BUL1
+	   ILEN = 0
+	   I = 1
+	   WIDTH = PAGE_WIDTH
+	   LEFT = .FALSE.
+	   DO WHILE (I.LE.NSYS_LINE.OR.ILEN.GT.0)  ! Write out system messages
+	      IF (ILEN.EQ.0) THEN
+	         CALL READ_QUEUE(%VAL(SYS_BUL),SYS_BUL,INPUT)
+		 ILEN = TRIM(INPUT)
+		 I = I + 1
+	      END IF
+	      IF (SYS_BUL.NE.0) THEN
+		 IF (PAGE.EQ.PAGE_LENGTH-2.AND.PAGING) THEN
+							! If at end of screen
+		    WRITE(6,1080)	! Ask for input to proceed to next page
+		    CALL GET_INPUT_NOECHO_PROMPT(INREAD(:1),
+     &			'HIT any key for next page....')
+	            WRITE (6,'(1X)')
+	            CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+		    PAGE = 1
+	            INREAD = '+'
+		 ELSE IF (WIDTH.EQ.PAGE_WIDTH.OR.LEFT) THEN 
+		    PAGE = PAGE + 1
+	            INREAD = ' '
+		 END IF
+		 IF (LEFT) THEN
+ 		    WRITE(6,1050) INREAD(:1)//INPUT(:ILEN)
+		    LEFT = .FALSE.
+	            ILEN = 0
+	            INREAD = '+'
+		 ELSE IF (ILEN.LE.WIDTH) THEN
+ 		    WRITE(6,1060) INREAD(:1)//INPUT(:ILEN)
+		    WIDTH = PAGE_WIDTH
+		    ILEN = 0
+		 ELSE
+		    DO WHILE (WIDTH.GT.0.AND.INPUT(WIDTH:WIDTH).NE.' ')
+	               WIDTH = WIDTH - 1
+		    END DO
+		    WRITE(6,1060) INREAD(:1)//INPUT(:WIDTH)
+	            INPUT = INPUT(WIDTH+1:)
+		    ILEN = ILEN - WIDTH
+		    DO WHILE (INPUT(:1).EQ.' '.AND.ILEN.GT.0)
+		       ILEN = ILEN - 1
+		       INPUT = INPUT(2:)
+	            END DO
+                    IF (INPUT(ILEN:ILEN).EQ.' ') THEN
+	               CONTINUE
+		    ELSE IF (ALPHA(INPUT(ILEN:ILEN))) THEN
+		       INPUT = INPUT(:ILEN)//' '
+		       ILEN = ILEN + 1
+		    ELSE
+		       INPUT = INPUT(:ILEN)//'  '
+		       ILEN = ILEN + 2
+		    END IF
+		    WIDTH = PAGE_WIDTH - ILEN
+		    IF (WIDTH.GT.0) THEN
+		       IF (ILEN.GT.0) LEFT = .TRUE.
+		    ELSE
+	               WIDTH = PAGE_WIDTH
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (NGEN.EQ.0) THEN
+	      WRITE (6,'(A)')		! Write delimiting blank line
+	   END IF
+	   PAGE = PAGE + 1
+	END IF
+
+	ENTRY REDISPLAY_DIRECTORY
+
+	GEN_DIR = GEN_DIR1
+	IF (NGEN.GT.0) THEN		! Are there new non-system messages?
+	   LENF = TRIM(FOLDER_NAME)
+	   S1 = (PAGE_WIDTH-13-LENF)/2
+	   S2 = PAGE_WIDTH-S1-13-LENF
+	   IF (PAGE+7+NGEN.GT.PAGE_LENGTH.AND.PAGE.GT.0) THEN
+	      WRITE(6,1080)		! Ask for input to proceed to next page
+	      CALL GET_INPUT_NOECHO_PROMPT(INREAD(:1),	! Get terminal input
+     &			'HIT any key for next page....')
+	      WRITE (6,'(1X)')
+	      CALL LIB$ERASE_PAGE(1,1)	! Clear the screen
+	      WRITE (6,'(''+'',A,$)') CTRL_G
+	      WRITE(6,1028) 'New '//FOLDER_NAME(:LENF)//' messages'
+	      PAGE = 1
+	   ELSE
+	      IF (FIRST_WRITE) THEN
+		 PAGE = 4		  ! Don't erase MAIL/PASSWORD notifies
+	         FIRST_WRITE = .FALSE. ! if this is first write to screen.
+	      END IF
+	      WRITE (6,'(''+'',A,$)') CTRL_G
+	      WRITE(6,1027) 'New '//FOLDER_NAME(:LENF)//' messages'
+	      PAGE = PAGE + 1
+	   END IF
+	   WRITE(6,1020)
+	   WRITE(6,1025)
+	   PAGE = PAGE + 2
+	   I = 0
+	   DO WHILE (I.LT.NGEN)
+	      I = I + 1
+	      CALL READ_QUEUE(%VAL(GEN_DIR),GEN_DIR,BULLDIR_ENTRY)
+	      CALL CONVERT_ENTRY_FROMBIN_FOLDER
+	      N = MAX(INT(LOG10(REAL(SYSTEM)))+1,3)
+	      N1 = MAX(1,6-N)
+	      IF (PAGE.EQ.PAGE_LENGTH-2.AND.PAGING) THEN ! If at end of screen
+		 WRITE(6,1080)	! Ask for input to proceed to next page
+		 CALL GET_INPUT_NOECHO_PROMPT(INREAD(:1),
+     &		'HIT Q(Quit listing) or any other key for next page....')
+	         CALL STR$UPCASE(INREAD(:1),INREAD(:1))
+	         WRITE (6,'(1X)')
+	         CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+		 PAGE = 1
+		 IF (INREAD(:1).EQ.'Q') THEN
+		    I = NGEN		! Quit directory listing
+		    WRITE(6,'(''+Quitting directory listing.'')')
+		 ELSE
+		    WRITE(6,1040) '+'//DESCRIP(:53),FROM,DATE(:6),SYSTEM
+		 END IF
+					! Bulletin number is stored in SYSTEM
+	      ELSE
+		 PAGE = PAGE + 1
+		 WRITE(6,1040) ' '//DESCRIP(:53),FROM,DATE(:6),SYSTEM
+	      END IF
+	   END DO
+	   IF ((.NOT.FOLDER_SET.AND.BTEST(SET_FLAG(1),0).AND.DIFF1.LE.0)
+     &		.OR.(FOLDER_SET.AND.TEST_SET_FLAG(FOLDER_NUMBER))) THEN
+	      PAGE = 0	! Don't reset page counter if READNEW not set,
+	   END IF	! as no prompt to read is generated.
+	END IF
+C
+C  Instruct users how to read displayed messages if READNEW not selected.
+C
+	IF (.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &		TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE(6,1030)
+	ELSE IF (NGEN.EQ.0) THEN
+	   ILEN = 57 + INDEX(COMMAND_PROMPT,'>') - 1
+	   S1 = (PAGE_WIDTH-ILEN)/2
+	   S2 = PAGE_WIDTH - S1 - ILEN
+	   WRITE(6,1035) 'The '//COMMAND_PROMPT(:ILEN-57)//
+     &		'/SYSTEM command can be used to reread these messages.'
+	   PAGE = PAGE + 1
+	ELSE
+	   FLEN = TRIM(FOLDER_NAME)
+	   IF (FOLDER_NUMBER.EQ.0) FLEN = -1
+	   ILEN = 30 + INDEX(COMMAND_PROMPT,'>') - 1 + FLEN
+	   S1 = (PAGE_WIDTH-ILEN)/2
+	   S2 = PAGE_WIDTH - S1 - ILEN
+	   IF (FOLDER_NUMBER.EQ.0) THEN
+	      WRITE(6,1035) 'Type ' //COMMAND_PROMPT(:ILEN-29)//
+     &		' to read these messages.'
+	   ELSE
+	      WRITE(6,1035) 'Type '//COMMAND_PROMPT(:ILEN-30-FLEN)
+     &		//' '//FOLDER_NAME(:FLEN)//
+     &		' to read these messages.'
+	   END IF
+	   PAGE = PAGE + 1
+	END IF
+
+9999	IF (LOGIN_SWITCH) THEN
+	   CALL COPY2(LOGIN_BTIM,LOGIN_BTIM_NEW)
+	   CALL COPY2(LOGIN_BTIM_SAVE,LOGIN_BTIM_OLD)
+	END IF
+	RETURN
+
+1020	FORMAT(' Description',43X,'From',9X,'Date',3X,'Number')
+1025	FORMAT(' -----------',43X,'----',9X,'----',3X,'------')
+1026	FORMAT(' ',<S1>('*'),A,' System Messages',<S2>('*'))
+1027	FORMAT(/,' ',<S1>('*'),A,<S2>('*'))
+1028	FORMAT('+',<S1>('*'),A,<S2>('*'))
+1030	FORMAT(' ',<PAGE_WIDTH>('*'))
+1035	FORMAT(' ',<S1>('*'),A,<S2>('*'))
+1040	FORMAT(A<53>,2X,A12,1X,A6,<N1>X,I<N>)
+1050	FORMAT(A,$)
+1060	FORMAT(A)
+1070	FORMAT(' ERROR: Cannot add new entry to user file.')
+1080	FORMAT(' ',/)
+
+	END
+
+
+	
+
+	SUBROUTINE GET_NODE_NUMBER_OTHER(NODE_NUMBER,NODE_AREA,NODE_NAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	CHARACTER*(*) NODE_NAME
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,SYI$_NODE_AREA,%LOC(NODE_AREA))
+	CALL ADD_2_ITMLST(4,SYI$_NODE_NUMBER,%LOC(NODE_NUMBER))
+	CALL END_ITMLST(GETSYI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETSYIW(,,NODE_NAME(:TRIM(NODE_NAME)),
+     &			%VAL(GETSYI_ITMLST),,,)	! Get Info command.
+
+	IF (.NOT.IER) THEN
+	   WRITE (6,'('' ERROR: Specified node name not found.'')')
+	   NODE_AREA = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DIRECTORY_HEADER(OUTLINE,PRINTING,EXTRACTING,EXPIRATION,
+     &		OUT)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	CHARACTER*(*) OUTLINE
+
+	IF (REMOTE_SET.GE.3) THEN
+	   WRITE (OUTLINE,'('' ['',I,''-'',I,'']'')')
+     &						F_START,F_NBULL
+	ELSE
+	   WRITE (OUTLINE,'('' [1-'',I,'']'')') NBULL
+	END IF
+	DO WHILE (INDEX(OUTLINE,'- ').GT.0)
+	   I = INDEX(OUTLINE,'- ')
+	   OUTLINE(I+1:) = OUTLINE(I+2:)
+	END DO
+	DO WHILE (INDEX(OUTLINE,'[ ').GT.0)
+	   I = INDEX(OUTLINE,'[ ')
+	   OUTLINE(I+1:) = OUTLINE(I+2:)
+	END DO
+	DO WHILE (INDEX(OUTLINE,'  ').LT.TRIM(OUTLINE))
+	   I = INDEX(OUTLINE,'  ')
+	   OUTLINE(I:) = OUTLINE(I+1:)
+	END DO
+	OUTLINE = FOLDER_NAME(:TRIM(FOLDER_NAME))//OUTLINE
+	BULL_PARAMETER = ' '
+	IF (READ_TAG) THEN
+	   IF (BTEST(READ_TAG,1)) THEN
+	      BULL_PARAMETER = 'MARKED'
+	   ELSE
+	      BULL_PARAMETER = 'SEEN'
+	   END IF
+	   IF (BTEST(READ_TAG,3)) THEN
+	      BULL_PARAMETER = 'UN'//BULL_PARAMETER
+	   END IF
+	END IF
+	IF (PRINTING) THEN
+	   BULL_PARAMETER = 'PRINTING '//BULL_PARAMETER
+	ELSE IF (EXTRACTING) THEN
+	   BULL_PARAMETER = 'EXTRACTING '//BULL_PARAMETER
+	END IF
+
+	IF (OUT.EQ.6) THEN 
+           WRITE (OUT,'(''+'',A,<PAGE_WIDTH-TRIM(BULL_PARAMETER)-
+     &		TRIM(OUTLINE)>X,A)')
+     &		BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &		OUTLINE(:TRIM(OUTLINE))
+           IF (EXPIRATION) THEN
+	      WRITE(OUT,1005) '    #'
+	   ELSE
+	      WRITE(OUT,1000) '    #'
+	   END IF
+	ELSE
+           WRITE (OUT,'(A,<PAGE_WIDTH-TRIM(BULL_PARAMETER)-
+     &		TRIM(OUTLINE)>X,A)')
+     &		BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &		OUTLINE(:TRIM(OUTLINE))
+           IF (EXPIRATION) THEN
+	      WRITE(OUT,1005) '   #'
+	   ELSE
+	      WRITE(OUT,1000) '   #'
+	   END IF
+	END IF
+
+1000	FORMAT(A,1X,'Description',43X,'From',9X,'Date',/)
+1005	FORMAT(A,1X,'Description',43X,'From',8X,'Expires',/)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_NEW_OR_SINCE(NEW,SINCE,IER,DATETIME)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	INTEGER TODAY(2)
+
+	CHARACTER DATETIME*24
+
+	IF (SINCE) THEN	 		! Was /SINCE specified?
+   	   IF (DATETIME.EQ.'TODAY') THEN	! TODAY is the default.
+	      	     IER = SYS$BINTIM('-- 00:00:00.00',TODAY)
+	      CALL GET_MSGKEY(TODAY,MSG_KEY)
+	   ELSE
+	      CALL SYS_BINTIM(DATETIME,MSG_BTIM)
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   END IF
+	   CALL READDIR_KEYGE(IER)
+	ELSE IF (NEW) THEN	! was /NEW specified?
+	   IF (REMOTE_SET.LT.3) THEN
+	      DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &		       F_NEWEST_BTIM)
+	      IF (DIFF.GE.0) THEN
+		 IER = 0
+	         RETURN
+	      ELSE
+	         CALL GET_MSGKEY(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				MSG_KEY)
+	      END IF
+	      CALL READDIR_KEYGE(IER)
+	   ELSE
+	      CALL NEWS_GET_NEWEST_MESSAGE(IER)
+	   END IF
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin1.for b/decus/vmslt98a/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..3d254eef0dda734d65e2b522342881afd884bc69
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin1.for
@@ -0,0 +1,2499 @@
+C
+C  BULLETIN1.FOR, Version 4/8/98
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE MAIL
+C
+C  SUBROUTINE MAIL
+C
+C  FUNCTION: Sends message which you have read to user via DEC mail.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /SENDTO/ SENDTO
+	CHARACTER*256 SENDTO
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	INCLUDE 'BULLDIR.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	IF (BTEST(CAPTIVE(-1),1)) THEN
+	   WRITE (6,'('' ERROR: MAIL invalid from DISMAIL account.'')')
+	   RETURN
+	END IF
+
+	IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	   WRITE(6,'('' ERROR: You have not read any message.'')')
+	   RETURN			! And return
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+
+	IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	   WRITE(6,'('' ERROR: Specified message was not found.'')')
+	   CALL CLOSE_BULLDIR		! If not, then error out
+	   RETURN
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	IF (CLI$PRESENT('EDIT')) THEN
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	END IF
+
+	OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &	   RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Error in opening scratch file.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('HEADER')) THEN		! Printout header?
+	   IF (EXDATE(8:11).LT.'1995') THEN
+	      IF (REMOTE_SET.NE.3) THEN
+		 INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   (DELETED)'
+	      ELSE
+		 INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+	      END IF
+	   ELSE IF ((SYSTEM.AND.4).EQ.4) THEN	! Is entry shutdown bulletin?
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Expires on shutdown'
+	   ELSE IF ((SYSTEM.AND.2).EQ.2) THEN	! Is entry permanent bulletin?
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Permanent'
+	   ELSE
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)//
+     &				'   Expires:   '//EXDATE//' '//EXTIME(:5)
+	   END IF
+	   IF ((SYSTEM.AND.1).EQ.1) THEN		! System bulletin?
+	      INPUT = INPUT(:TRIM(INPUT))//' / System'
+	   END IF
+	   WRITE (3,'(A)') INPUT(:TRIM(INPUT))
+	END IF
+
+	HEAD = CLI$PRESENT('HEADER')
+
+	CALL OPEN_BULLFIL_SHARED	! Open BULLETIN file
+
+	ILEN = LINE_LENGTH + 1
+
+	CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	   IF (HEAD) WRITE(3,1060) INPUT(7:ILEN)
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	ELSE IF (HEAD) THEN
+	   WRITE(3,1060) FROM
+	END IF
+
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	   IF (HEAD) WRITE(3,1050) INPUT(7:ILEN)
+	   SUBJECT_LINE = INPUT(7:ILEN)
+	ELSE
+	   IF (HEAD) WRITE(3,1050) DESCRIP
+	   IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   SUBJECT_LINE = DESCRIP
+	END IF
+
+	IF (CLI$PRESENT('SUBJECT')) THEN
+	   IER = CLI$GET_VALUE('SUBJECT',SUBJECT_LINE,LEN_D)
+	END IF
+
+	DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	END DO
+
+	CLOSE (UNIT=3)			! Message copy completed
+
+	CALL CLOSE_BULLFIL
+
+	LEN_D = TRIM(SUBJECT_LINE)
+	IF (LEN_D.EQ.0) THEN
+	   SUBJECT_LINE = 'BULLETIN message.'
+	   LEN_D = TRIM(SUBJECT_LINE)
+	END IF
+
+	I = 1
+	DO WHILE (I.LE.LEN_D)
+	   IF (SUBJECT_LINE(I:I).EQ.'"') THEN
+	      IF (LEN_D.EQ.64) THEN
+		 SUBJECT_LINE(I:I) = '`'
+	      ELSE
+		 SUBJECT_LINE = SUBJECT_LINE(:I)//'"'//SUBJECT_LINE(I+1:)
+		 I = I + 1
+		 LEN_D = LEN_D + 1
+	      END IF
+	   END IF
+	   I = I + 1
+	END DO
+
+	LEN_S = 0
+	DO WHILE (CLI$GET_VALUE('RECIPIENTS',SENDTO(LEN_S+1:),I)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get all the usernames
+	   LEN_S = LEN_S + I + 1
+	   SENDTO(LEN_S:LEN_S) = ','
+	END DO
+	LEN_S = LEN_S - 1
+
+	I = 1		! Must change all " to """ in MAIL recipients
+	DO WHILE (I.LE.LEN_S)
+	   IF (SENDTO(I:I).EQ.'"') THEN
+	      SENDTO = SENDTO(:I)//'""'//SENDTO(I+1:)
+	      I = I + 2
+	      LEN_S = LEN_S + 2
+	   END IF
+	   I = I + 1
+	END DO
+
+	IF (CLI$PRESENT('EDIT')) THEN
+	   CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	   CONTEXT = 0
+	   IER =  LIB$FIND_FILE('SYS$LOGIN:BULL.SCR',INPUT,CONTEXT)
+	   VERSION = INDEX(INPUT,';') + 1
+	   IF (INPUT(VERSION:VERSION).EQ.'1') THEN
+	      CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	      WRITE (6,'('' ERROR: No message mailed.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	CALL DISABLE_PRIVS
+	CALL SENDMAIL('SYS$LOGIN:BULL.SCR',SENDTO(:LEN_S)
+     &			,SUBJECT_LINE,STATUS)
+C       CALL LIB$SPAWN('$MAIL SYS$LOGIN:BULL.SCR '//SENDTO(:LEN_S)
+C     &    //'/SUBJECT="'//SUBJECT_LINE(:LEN_D)//'"',,,,,,STATUS)
+C	IF (.NOT.STATUS) CALL SYS_GETMSG(STATUS)
+
+	CALL ENABLE_PRIVS
+	CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+
+	RETURN
+
+1050	FORMAT('Description: ',A,/)
+1060	FORMAT('From: ',A)
+
+	END
+
+
+
+	SUBROUTINE MODIFY_FOLDER
+C
+C  SUBROUTINE MODIFY_FOLDER
+C
+C  FUNCTION: Modifies a folder's information.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER RESPONSE*32
+
+	IF (.NOT.FOLDER_ACCESS
+     &		 (USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   WRITE (6,'('' ERROR: No privileges to modify folder.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('NAME')) THEN
+	   IF (REMOTE_SET) THEN
+	      WRITE (6,'('' ERROR: Cannot change name of'',
+     &				'' remote folder.'')')
+	      RETURN
+	   ELSE
+	      CALL CLI$GET_VALUE('NAME',FOLDER1,LEN_P)
+	      IF (LEN_P.GT.44) THEN
+		 WRITE (6,'('' ERROR: Folder name cannot be larger
+     &				than 44 characters.'')')
+		 RETURN
+	      END IF
+	   END IF
+	ELSE
+	   FOLDER1 = FOLDER
+	END IF
+
+	INIT_NEWSFEED = .FALSE.
+
+	NEWSGROUP = .FALSE.
+	MAILTO = 0
+
+	IF (CLI$PRESENT('DESCRIPTION')) THEN
+	   WRITE (6,'('' Enter one line description of folder.'')')
+	   LENF = 81
+	   DO WHILE (LENF.GT.80)
+	      CALL GET_LINE(FOLDER1_DESCRIP,LENF)	! Get input line
+	      IF (LENF.LE.0) THEN
+		 WRITE (6,'('' ERROR: Folder modification aborted.'')')
+		 RETURN
+	      ELSE IF (LENF.GT.80) THEN			! If too many characters
+		 WRITE (6,'('' ERROR: Description must be < 80 characters.'')')
+	         RETURN
+	      ELSE
+		 FOLDER1_DESCRIP = FOLDER1_DESCRIP(:LENF) ! End fill with spaces
+	      END IF
+	   END DO
+	   I = INDEX(FOLDER1_DESCRIP,'<')
+	   J = INDEX(FOLDER1_DESCRIP,'>')
+	   IF (I.GT.0.AND.J.GT.I.AND.(INDEX(FOLDER1_DESCRIP(I:),'@').LT.1
+     &	       .OR.INDEX(FOLDER1_DESCRIP(I:),'@').GT.J-I+1).AND.
+     &	       (INDEX(FOLDER1_DESCRIP(I:),'.')
+     &	       .LE.J-I+1.AND.INDEX(FOLDER1_DESCRIP(I:),'.').GT.0)) THEN
+	      NEWSGROUP = .TRUE.
+	      WRITE (6,'('' Init news feed counter to feed '',
+     &			 ''all messages in news group (Y),'')')
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &		 'or set to feed only new messages (N,default) ? ')
+	      INIT_NEWSFEED = RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y'
+	      I = INDEX(FOLDER1_DESCRIP,'[')
+	      J = INDEX(FOLDER1_DESCRIP,']')
+	   END IF
+	   IF (I.GT.0.AND.J.GT.I.AND.
+     &	       (INDEX(FOLDER1_DESCRIP(I:),'@').GT.1.AND.
+     &	       INDEX(FOLDER1_DESCRIP(I:),'@').LT.J-I+1)) THEN
+	      MAILTO = 1
+	   END IF
+	   IF (I.GT.0.AND.J.GT.I.AND.(INDEX(FOLDER1_DESCRIP(I:),'.')
+     &	       .GT.J-I+1.OR.INDEX(FOLDER1_DESCRIP(I:),'.').EQ.0)
+     &	       .AND.MAILTO.EQ.0.AND..NOT.BTEST(FOLDER_FLAG,11)
+     &	       .AND..NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Have you specified '//
+     &		   'an email address in the description? (default=N) ')
+	      IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') MAILTO = 1
+	   END IF
+	   IF (MAILTO.EQ.1.AND..NOT.BTEST(FOLDER_FLAG,11).AND.
+     &	       .NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	      WRITE (6,'('' A mailing address has been specified.'')')
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Will messages be '//
+     &		'sent to and received from this address? (default=N) ')
+	      IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') THEN
+	         MAILTO = 2
+		 WRITE (6,'('' SET POST_ONLY will be issued.'')')
+	      ELSE
+		 MAILTO = 3
+		 WRITE (6,'('' SET ADD_ONLY will be issued.'')')
+	      END IF
+	   END IF
+	ELSE
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP
+	END IF
+
+	IF (CLI$PRESENT('OWNER')) THEN
+	   CALL CLI$GET_VALUE('OWNER',FOLDER1_OWNER,LEN_P)
+	   IF (LEN_P.GT.12) THEN
+	      WRITE (6,'('' ERROR: Owner name must be < 13 characters.'')')
+	      RETURN
+	   ELSE IF (CLI$PRESENT('ID')) THEN
+	      IER = CHKPRO(FOLDER1_OWNER)
+	   ELSE
+	      CALL GET_UAF
+     &		   (FOLDER1_OWNER,USERB1,GROUPB1,ACCOUNTB1,FLAGS,IER)
+	   END IF
+	   IF (.NOT.IER) THEN
+	      WRITE (6,'('' ERROR: Owner name is not valid username.'')')
+	      RETURN
+	   ELSE IF (LEN_P.GT.LEN(FOLDER1_OWNER)) THEN
+	      WRITE (6,'('' ERROR: Folder owner name too long.'')')
+	      RETURN
+	   ELSE IF (.NOT.SETPRV_PRIV()) THEN
+	      WRITE(6,'('' Enter password of new owner: '',A)') CHAR(10)
+	      CALL GET_INPUT_NOECHO(RESPONSE)
+	      IF (TRIM(RESPONSE).EQ.0) THEN
+		 WRITE (6,'('' ERROR: No password entered.'')')
+		 RETURN
+	      END IF
+	      WRITE (6,'('' Attempting to verify password name...'')')
+	      OPEN (UNIT=10,NAME='SYS$NODE"'//
+     &		   FOLDER1_OWNER(:TRIM(FOLDER1_OWNER))
+     &		   //' '//RESPONSE(:TRIM(RESPONSE))//'"::',
+     &		   TYPE='SCRATCH',IOSTAT=IER)
+	      CLOSE (UNIT=10)
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' ERROR: Password is invalid.'')')
+		 RETURN
+	      ELSE
+		 WRITE (6,'('' Password was verified.'')')
+	      END IF
+	   ELSE
+	      FOLDER1_OWNER = FOLDER1_OWNER(:LEN_P)
+	   END IF
+	ELSE
+	   FOLDER1_OWNER = FOLDER_OWNER
+	END IF
+
+	CALL OPEN_BULLFOLDER		! Open folder file
+
+	IF (CLI$PRESENT('NAME')) THEN
+	   READ (7,IOSTAT=IER,KEY=FOLDER1,KEYID=0)
+	   				! See if folder exists
+	   IF (IER.EQ.0) THEN
+	      WRITE (6,'('' ERROR: Folder name already exists.'')')
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   END IF
+	END IF
+
+	CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	IF (IER.EQ.0.AND.CLI$PRESENT('NAME')) THEN
+	   LEN_F = TRIM(FOLDER_DIRECTORY)
+	   IER = LIB$RENAME_FILE(FOLDER_DIRECTORY(:LEN_F)//
+     &		FOLDER(:TRIM(FOLDER))//'.*',FOLDER_DIRECTORY(:LEN_F)//
+     &		FOLDER1(:TRIM(FOLDER1))//'.*')
+	   IF (.NOT.IER) THEN
+	      I = 0
+	      IER1 = LIB$FIND_FILE(FOLDER_DIRECTORY(:LEN_F)//
+     &		FOLDER(:TRIM(FOLDER))//'.*',INPUT,I)
+	   END IF
+	   IF (IER.OR..NOT.IER1) THEN
+	      FOLDER_FILE = FOLDER_DIRECTORY(:LEN_F)//FOLDER1
+	      FOLDER_NAME = FOLDER1
+	      IER = 0
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   IF (CLI$PRESENT('OWNER')) THEN
+	      CALL CHKACL
+     &		(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',IER)
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+		 CALL ADD_ACL(FOLDER1_OWNER,'R+W+C',IER)
+		 CALL DEL_ACL(FOLDER_OWNER,'R+W+C',IER)
+	      END IF
+	   END IF
+	   FOLDER = FOLDER1
+	   FOLDER_OWNER = FOLDER1_OWNER
+	   FOLDER_DESCRIP = FOLDER1_DESCRIP
+	   DELETE (7)
+	   IF (CLI$PRESENT('ID')) THEN
+	      FOLDER_FLAG = IBSET(FOLDER_FLAG,6)
+	   ELSE
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,6)
+	   END IF
+	   IF (NEWSGROUP) FOLDER_FLAG = IBSET(FOLDER_FLAG,4)
+	   IF (MAILTO.EQ.2) FOLDER_FLAG = IBSET(FOLDER_FLAG,10)
+	   IF (MAILTO.EQ.3) FOLDER_FLAG = IBSET(FOLDER_FLAG,11)
+	   IF (INIT_NEWSFEED) THEN
+	      F_LAST = 0
+	   ELSE IF (NEWSGROUP) THEN
+	      CALL CLOSE_BULLFOLDER
+	      CALL OPEN_BULLNEWS_SHARED
+	      I = INDEX(FOLDER_DESCRIP,'<') + 1
+	      J = INDEX(FOLDER_DESCRIP,'>') - 1
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER_DESCRIP(I:J),IER)
+	      CALL CLOSE_BULLNEWS
+	      CALL OPEN_BULLFOLDER
+	      F_LAST = F1_NBULL
+	   END IF
+	   CALL WRITE_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) WRITE (6,'('' Folder successfully modified.'')')
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Folder modification aborted.'')')
+	END IF
+
+	CALL CLOSE_BULLFOLDER
+
+	RETURN
+	END
+
+
+
+	FUNCTION FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) USERNAME,FOLDER_OWNER
+
+	IF (SETPRV_PRIV()) THEN
+	   FOLDER_ACCESS = .TRUE.
+	ELSE IF (BTEST(FOLDER_FLAG,6)) THEN	! If folder owner is ID
+	   FOLDER_ACCESS = CHKPRO(FOLDER_OWNER)
+	ELSE
+	   FOLDER_ACCESS = USERNAME.EQ.FOLDER_OWNER
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE MOVE(DELETE_ORIGINAL)
+C
+C  SUBROUTINE MOVE
+C
+C  FUNCTION: Moves message from one folder to another.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REMOTE_READ_MESSAGE/ SCRATCH_R1
+	DATA SCRATCH_R1 /0/
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /HEADER/ HEADER
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	COMMON /NEWS2BULL/ NEWS2BULL
+
+	COMMON /FEED/ FEED
+
+        COMMON /MAIL_INFO/ USE_INFROM
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /BULLCP_NEWS/ BULLCP_NEWS
+
+	EXTERNAL CLI$_ABSENT,BULLETIN_SUBCOMMANDS
+
+	LOGICAL DELETE_ORIGINAL
+
+	CHARACTER SAVE_FOLDER*44,POST_SUBJECT*256,TODAY*24
+	CHARACTER SCRFILE*18
+
+	DATA TEMP_FILE/.FALSE./
+
+	DIMENSION BTIM(2)
+
+	ORIGINAL = CLI$PRESENT('ORIGINAL')
+
+	IF (ORIGINAL.AND..NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: You have no privileges to keep''
+     &			,'' original owner.'')')
+	   RETURN
+	END IF
+
+	ALL = CLI$PRESENT('ALL')
+
+	MERGE = CLI$PRESENT('MERGE')
+
+	SAVE_BULL_POINT = BULL_POINT
+
+	FROM_REMOTE = REMOTE_SET
+	CALL CLI$GET_VALUE('FOLDER',FOLDER1)
+	IF (INDEX(FOLDER1,'.').GT.0) CALL LOWERCASE(FOLDER1)
+	TO_NEWS = TEST_NEWS(FOLDER1)
+	IF (.NOT.BULLCP_NEWS.AND.FOLDER.EQ.FOLDER1) THEN
+	   WRITE (6,'('' ERROR: Destination cannot be same as'',
+     &		      '' current location.'')')
+	   RETURN
+	END IF
+
+	IER1 = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER1.EQ.%LOC(CLI$_ABSENT).AND..NOT.ALL) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no message has been read
+	      WRITE(6,'('' ERROR: You are not reading any message.'')')
+	      RETURN			! and return
+	   END IF
+
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(BULL_POINT,IER)		! Get message directory entry
+	   IF (IER.NE.BULL_POINT+1.OR.BULL_POINT.NE.SAVE_BULL_POINT) THEN
+	      WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      CALL CLOSE_BULLDIR
+	      BULL_POINT = SAVE_BULL_POINT
+	      RETURN
+	   END IF
+
+	   NUM_COPY = 1
+	ELSE
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(0,IER)		! Get message directory entry
+	   IF (NBULL.EQ.0) THEN		! Were messages found?
+	      WRITE(6,'('' ERROR: No messages were found.'')')
+	      CALL CLOSE_BULLDIR
+	      RETURN
+	   END IF
+
+	   IF (IER1.NE.%LOC(CLI$_ABSENT)) THEN
+	      CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER1)
+	      IF (EBULL.GT.F_NBULL) EBULL = F_NBULL
+	      IF (SBULL.LE.0.OR.IER1.NE.0) THEN
+		 WRITE (6,'(A)')
+     &		  ' ERROR: Specified message number has incorrect format.'
+		 CALL CLOSE_BULLDIR
+		 RETURN
+	      ELSE
+		 NUM_COPY = EBULL - SBULL + 1
+		 BULL_POINT = SBULL
+	      END IF
+	      IF (NUM_COPY.GT.1) ALL = .TRUE.
+	      IF (INDEX(BULL_PARAMETER,'LAST').GT.0.AND.ORIGINAL) THEN
+	         NEWGROUP = .TRUE.	! Kludgey way of detecting new2bull
+	         NEXT = .TRUE.		! If SBULL does not exist, will find
+              ELSE			! next message after SBULL
+	         SBULL1 = SBULL
+	   	 CALL READDIR(SBULL,IER)
+	   	 IF (IER.NE.SBULL+1.OR.SBULL.NE.SBULL1) THEN
+		    WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      	    CALL CLOSE_BULLDIR
+	      	    RETURN
+	         END IF
+	      END IF
+	   ELSE IF (ALL) THEN
+	      NUM_COPY = NBULL
+	      BULL_POINT = 1
+	      NEWGROUP = .TRUE.
+	      NEXT = .TRUE.
+	   END IF
+	END IF
+
+	IF (REMOTE_SET.OR.REMOTE_SET.EQ.4) THEN
+	   IF (.NOT.TEMP_FILE) THEN
+	      OPEN (UNIT=12,FILE='REMOTE.BULLDIR',
+     &		 STATUS='SCRATCH',FORM='UNFORMATTED',IOSTAT=IER)
+	      IF (IER.EQ.0) THEN
+		 OPEN (UNIT=11,FILE='REMOTE.BULLFIL',
+     &		    STATUS='SCRATCH',IOSTAT=IER,
+     &		    ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &		    FORM='UNFORMATTED')
+	      END IF
+	   ELSE
+	      REWIND (12,IOSTAT=IER)
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      TEMP_FILE = .TRUE.
+	      CALL OPEN_BULLFIL
+	      CALL READDIR(0,IER)
+	      I = BULL_POINT - 1
+	      IER = I + 1
+	      NBLOCK = 1
+	      LAST = BULL_POINT+NUM_COPY-1
+	      NUM_COPY = 0
+	      DO WHILE (I.LT.LAST.AND.IER.EQ.I+1)
+		 I = I + 1
+		 CALL READDIR(I,IER)
+		 IF (IER.EQ.I+1.AND.I.LE.LAST) THEN
+		    CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+		    IF (REMOTE_SET) THEN
+		       CALL REMOTE_READ_MESSAGE(I,IER1)
+		       IF (IER1.GT.0) THEN
+			  CALL DISCONNECT_REMOTE
+		       ELSE
+			  CALL GET_REMOTE_MESSAGE(IER1)
+		       END IF
+		    ELSE
+		       IER1 = 0
+		    END IF
+		    IF (LENGTH.EQ.0) IER1 = 1	! Don't allow empty messages
+		    IF (IER1.EQ.0) THEN
+		       SCRATCH_R = SCRATCH_R1
+		       DO J=1,LENGTH
+			  IF (REMOTE_SET) THEN
+			     CALL READ_QUEUE(%VAL(SCRATCH_R),
+     &					SCRATCH_R,INPUT(:128))
+			  ELSE
+			     READ (1'BLOCK+J-1,IOSTAT=IER1) INPUT(:128)
+			  END IF
+			  WRITE (11'NBLOCK+J-1,IOSTAT=IER1) INPUT(:128)
+		       END DO
+		    END IF
+		    NEWS2BULL = NEWS2BULL.AND..NOT.TO_NEWS.AND.ORIGINAL
+		    IF (IER1.EQ.0.AND..NOT.NEWS2BULL) THEN
+		       BLOCK = NBLOCK
+		       NBLOCK = NBLOCK + LENGTH
+		       WRITE (12,IOSTAT=IER1) BULLDIR_ENTRY
+		    END IF
+		    IF (TO_NEWS.AND.ORIGINAL) THEN
+		       WRITE (12,IOSTAT=IER1) NEWS_MSGID
+		    END IF
+		    IF (IER1.NE.0) THEN
+		       I = IER
+		    ELSE IF (.NOT.NEWS2BULL) THEN
+		       NUM_COPY = NUM_COPY + 1
+		    END IF
+		    NEWS2BULL = .FALSE.
+		 END IF
+	      END DO
+	      CALL CLOSE_BULLFIL
+	   END IF
+	   IF (IER1.NE.0.OR..NOT.TEMP_FILE.OR.NUM_COPY.EQ.0) THEN
+	      WRITE(6,'('' ERROR: Copy aborted. Remote folder problem.'')')
+	      CLOSE (UNIT=12)
+	      CLOSE (UNIT=11)
+	      TEMP_FILE = .FALSE.
+	      CALL CLOSE_BULLDIR
+	      RETURN
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	SAVE_FOLDER = FOLDER
+	SAVE_FOLDER_NUMBER = FOLDER_NUMBER
+
+	FOLDER_NUMBER = -1	! Use FOLDER as key rather than FOLDER_NUMBER
+	FROM_BULL_POINT = BULL_POINT
+	CALL SELECT_FOLDER(.FALSE.,IER)
+
+	IER1 = .TRUE.
+
+	POST_NEWS = (REMOTE_SET.EQ.4.AND..NOT.BULLCP_NEWS).OR.REMOTE_SET.EQ.3
+
+	POST_FEED = .FALSE.
+	SLIST = 0
+	IF (.NOT.IER) THEN
+	   WRITE (6,'('' ERROR: Cannot access specified folder.'')')
+	ELSE IF (READ_ONLY.OR.(MERGE.AND.REMOTE_SET.GT.0)) THEN
+	   IF (READ_ONLY) THEN
+	      WRITE (6,'('' ERROR: No access to write into folder.'')')
+	   ELSE
+	      WRITE (6,'('' ERROR: /MERGE invalid into remote folder.'')')
+	   END IF
+	   IER1 = .FALSE.
+	ELSE IF (REMOTE_SET.EQ.0) THEN
+	   IF (.NOT.CLI$PRESENT('LOCAL').AND.NEWS_FEED()) THEN
+	      SLIST = INDEX(FOLDER_DESCRIP,'<') + 1
+	      FOLDER1_DESCRIP =
+     &		FOLDER_DESCRIP(SLIST:INDEX(FOLDER_DESCRIP,'>')-1)
+	      POST_FEED = .TRUE.
+	   END IF
+	   IF (NEWS_FEED()) THEN
+	      SLIST = INDEX(FOLDER_DESCRIP,'[') + 1
+	   ELSE
+	      SLIST = INDEX(FOLDER_DESCRIP,'<') + 1
+	   END IF
+	   IF (SLIST.GT.1) THEN
+	      IF (NEWS_FEED()) THEN
+	         ELIST = INDEX(FOLDER_DESCRIP,']') - 1
+	      ELSE
+	         ELIST = INDEX(FOLDER_DESCRIP,'>') - 1
+	      END IF
+	   END IF
+	   IF (CLI$PRESENT('LOCAL').AND..NOT.BULLCP_NEWS) SLIST = 0
+	END IF
+
+	IF (.NOT.IER.OR..NOT.IER1) THEN
+	   FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	   IF (.NOT.IER) THEN
+	      FOLDER = SAVE_FOLDER
+	      BULL_POINT = SAVE_BULL_POINT
+	   ELSE
+	      FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	      FOLDER1 = SAVE_FOLDER
+	      CALL SELECT_FOLDER(.FALSE.,IER1)
+	   END IF
+	   BULL_POINT = SAVE_BULL_POINT
+	   CLOSE (UNIT=12)
+	   CLOSE (UNIT=11)
+	   TEMP_FILE = .FALSE.
+	   RETURN
+	END IF
+C
+C  Add bulletin to bulletin file and directory entry for to directory file.
+C
+	IF (POST_NEWS.OR.(POST_FEED.AND.SLIST.LE.1)) THEN
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='SCRATCH',CARRIAGECONTROL='LIST')
+	   SCRFILE = 'SYS$LOGIN:BULL.SCR'
+	END IF
+	IF (.NOT.POST_NEWS) THEN
+	   CALL OPEN_BULLDIR			! Prepare to add dir entry
+	   IF (REMOTE_SET.EQ.4) THEN            ! In case exdate has bad date
+	      IF (FOLDER_BBEXPIRE.GT.0) THEN
+		 EX = FOLDER_BBEXPIRE
+	      ELSE
+		 EX = NEWS_EXPIRE_DEFAULT
+	      END IF
+	      CALL GET_EXDATE(EXDATE,EX)
+	      CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	      EXTIME = TODAY(13:)
+	   END IF
+	   CALL OPEN_BULLFIL			! Prepare to add bulletin
+
+	   CALL READDIR(0,IER)			! Get NBLOCK
+	   IF (IER.EQ.0.AND.REMOTE_SET.LT.3) NBLOCK = 0
+	END IF
+
+	FOLDER1_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//SAVE_FOLDER
+
+	IF (.NOT.FROM_REMOTE.AND.FROM_REMOTE.NE.4) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	      OPEN (UNIT=12,FILE=FOLDER1_FILE(:TRIM(FOLDER1_FILE))
+     &		//'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &		RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &		ORGANIZATION='INDEXED',IOSTAT=IER,
+     &		KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	   END DO
+
+	   IF (IER.EQ.0) THEN
+	      DO WHILE (FILE_LOCK(IER,IER1))
+		 OPEN (UNIT=11,FILE=FOLDER1_FILE(:TRIM(FOLDER1_FILE))
+     &		   //'.BULLFIL',STATUS='UNKNOWN',IOSTAT=IER,
+     &		   ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &		   FORM='UNFORMATTED')
+	      END DO
+	   END IF
+	ELSE
+	   IER= 0
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+	   SAVE_HEADER = HEADER
+	   IF (CLI$PRESENT('HEADER')) THEN
+	      HEADER = .TRUE.
+	   ELSE
+	      HEADER = .FALSE.
+	   END IF
+	END IF
+
+	IF (MERGE) CALL INITIALIZE_MERGE(IER)
+
+	START_BULL_POINT = BULL_POINT
+
+	IF (IER.EQ.0) THEN
+	   IF (FROM_REMOTE.OR.FROM_REMOTE.EQ.4) THEN
+	      REWIND (12)
+	   ELSE
+	      READ (12,KEYID=0,KEY=FROM_BULL_POINT-1,IOSTAT=IER)
+	   END IF
+	END IF
+
+	DO WHILE (NUM_COPY.GT.0.AND.IER.EQ.0)
+	   READ (12,IOSTAT=IER) BULLDIR_ENTRY
+	   IF ((FROM_REMOTE.OR.FROM_REMOTE.EQ.4).AND.
+     &	       (TO_NEWS.AND.ORIGINAL)) THEN
+	      READ (12,IOSTAT=IER) NEWS_MSGID
+	   END IF
+	   NUM_COPY = NUM_COPY - 1
+
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   CALL CONVERT_ENTRY_FROMBIN_FOLDER
+
+	   IF (REMOTE_SET.GE.3) SYSTEM = 0
+
+	   IF (FROM_REMOTE.GE.3.AND.REMOTE_SET.LE.3) THEN
+	      SYSTEM = 0
+	      IF (FOLDER_BBEXPIRE.GT.0) THEN
+		 CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      ELSE IF (FOLDER_BBEXPIRE.EQ.-1) THEN   ! Permanent message
+		 EXDATE = '5-NOV-2100'
+		 SYSTEM = 2
+	      ELSE IF (EX_BTIM(1).EQ.0.AND.EX_BTIM(2).EQ.0) THEN
+		 CALL GET_EXDATE(EXDATE,14)
+	      END IF
+	   ELSE IF (REMOTE_SET.EQ.4.AND.ORIGINAL) THEN
+	      IF (EX_BTIM(1).NE.0.OR.EX_BTIM(2).NE.0) THEN
+		 LIMIT = NEWS_F_EXPIRE_LIMIT
+		 IF (LIMIT.EQ.0) LIMIT = NEWS_EXPIRE_LIMIT_DEFAULT
+		 IF (LIMIT.GT.0) THEN
+		    CALL GET_EXDATE(EXDATE,LIMIT)
+		    CALL SYS_BINTIM(EXDATE,BTIM)
+		    IF (COMPARE_BTIM(BTIM,EX_BTIM).LT.0) THEN
+		       CALL COPY2(EX_BTIM,BTIM)
+		    END IF
+		 END IF
+		 CALL SYS$ASCTIM(,EXDATE,EX_BTIM,)
+		 IF (COMPARE_DATE(EXDATE,' ').LE.0) THEN
+		    IER = 0
+		    GO TO 100
+		 END IF
+	      ELSE
+		 IF (FOLDER_BBEXPIRE.GT.0) THEN
+		    EX = FOLDER_BBEXPIRE
+		 ELSE
+		    EX = NEWS_EXPIRE_DEFAULT
+		 END IF
+		 IF (F_LAST.EQ.0) THEN
+		    EX = EX + COMPARE_DATE(DATE,' ')
+		    IF (EX.LE.0) THEN
+		       IER = 0
+		       GO TO 100
+		    END IF
+		 END IF
+		 CALL GET_EXDATE(EXDATE,EX)
+	      END IF
+	      CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	      EXTIME = TODAY(13:)
+	   END IF
+
+	   IF (.NOT.BTEST(FOLDER_FLAG,2).OR.	! Not system folder?
+     &		 .NOT.SETPRV_PRIV()) THEN	! Or no privileges?
+	      SYSTEM = IBCLR(SYSTEM,0)		! Remove system bit
+	   END IF
+
+	   IF (BTEST(SYSTEM,2).AND.		! Shutdown message?
+     &	    (.NOT.BTEST(FOLDER_FLAG,2).OR.	! Not system folder?
+     &		 .NOT.SETPRV_PRIV())) THEN	! Or no privileges?
+	      SYSTEM = IBCLR(SYSTEM,2)		! Remove shutdown bit
+	      WRITE (6,'('' ERROR: No privileges to add'',
+     &				'' shutdown message.'')')
+	      IF (FOLDER_BBEXPIRE.GT.0) THEN
+		 CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+		 WRITE (6,'('' Expiration will be '',I,'' days.'')')
+     &				FOLDER_BBEXPIRE
+	      ELSE
+		 CALL GET_EXDATE(EXDATE,14)
+		 WRITE (6,'('' Expiration will be '',I,'' days.'')') 14
+	      END IF
+	      EXTIME = '00:00:00.00'
+	   ELSE IF (BTEST(SYSTEM,1).AND.	! Permanent?
+     &		F_EXPIRE_LIMIT.GT.0.AND..NOT.   ! Expiration limit present?
+     &		FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	      WRITE (6,'('' ERROR: No privileges to add'',
+     &				'' permanent message.'')')
+	      WRITE (6,'('' Expiration will be '',I,'' days.'')')
+     &				F_EXPIRE_LIMIT
+	      SYSTEM = IBCLR(SYSTEM,1)
+	      CALL GET_EXDATE(EXDATE,F_EXPIRE_LIMIT)
+	      EXTIME = '00:00:00.00'
+	   END IF
+
+	   IF (.NOT.ORIGINAL) THEN	! If not /ORIGINAL
+	      FROM = USERNAME		! Specify owner
+	   END IF
+
+	   IF (REMOTE_SET.EQ.1) THEN
+	      WRITE (REMOTE_UNIT,'(A)',IOSTAT=IER) 2
+	      IF (IER.NE.0) CALL ERROR_AND_EXIT
+	   END IF
+
+	   IF (SLIST.GT.1.OR.POST_NEWS.OR.POST_FEED) THEN
+	      BLOCK_SAVE = BLOCK
+	      LENGTH_SAVE = LENGTH
+	      IF (SLIST.GT.1) THEN
+		 OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		   RECL=LINE_LENGTH,CARRIAGECONTROL='LIST')
+	         SCRFILE = 'SYS$LOGIN:BULL.SCR'
+		 IF (IER.NE.0) THEN
+	      	    OPEN(UNIT=3,FILE='BULL.SCR',IOSTAT=IER,
+     &		       RECL=LINE_LENGTH,CARRIAGECONTROL='LIST')
+	      	    SCRFILE = 'BULL.SCR'
+		 END IF
+	      ENDIF
+	      ILEN = LINE_LENGTH + 1
+
+	      INFROM = FROM
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	         INFROM = INPUT(7:)
+		 CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+		 POST_SUBJECT = INPUT(7:ILEN)
+	      ELSE
+		 POST_SUBJECT = DESCRIP
+		 IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	      END IF
+
+	      DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+		 CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		 IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(1:ILEN)
+	      END DO
+
+	      REWIND (UNIT=3)
+
+	      IF (POST_NEWS.OR.POST_FEED) THEN
+	         USE_INFROM = ORIGINAL
+	         IF (CLI$PRESENT('LOCAL')) NEWS2BULL = .TRUE.
+	         CALL NEWS_POST
+     &		    (SCRFILE(:TRIM(SCRFILE)),.TRUE.,IER,POST_SUBJECT)
+		 NEWS2BULL = .FALSE.
+	      END IF
+	      IF (SLIST.GT.1) THEN
+		 CLOSE (UNIT=3)
+		 USE_INFROM = ORIGINAL
+		 IF (BTEST(FOLDER_FLAG,10).OR.BTEST(FOLDER_FLAG,15)) THEN
+	            CALL RESPOND_MAIL(SCRFILE(:TRIM(SCRFILE)),
+     &		       FOLDER_DESCRIP(SLIST:ELIST),
+     &		       POST_SUBJECT(:TRIM(POST_SUBJECT)),STATUS)
+		 ELSE
+	            CALL RESPOND_MAIL(SCRFILE(:TRIM(SCRFILE)),
+     &		       FOLDER_DESCRIP(SLIST:ELIST),
+     &	   	       FOLDER(:TRIM(FOLDER))//' folder message: '//
+     &		       POST_SUBJECT(:TRIM(POST_SUBJECT)),STATUS)
+		 END IF
+		 CALL LIB$DELETE_FILE(SCRFILE(:TRIM(SCRFILE))//';')
+	      ELSE IF (POST_FEED.OR.POST_NEWS) THEN
+		 REWIND (UNIT=3)
+	      END IF
+	      BLOCK = BLOCK_SAVE
+	      LENGTH = LENGTH_SAVE
+	   END IF
+	   IF (.NOT.POST_NEWS) THEN
+	      IF (MERGE) CALL ADD_MERGE_TO(IER)
+
+	      IF (REMOTE_SET.EQ.4) CALL SET_BULLFIL_UPDATE
+
+	      IF (IER.EQ.0) THEN
+		 NBLOCK = NBLOCK + 1
+
+		 DO I=BLOCK,BLOCK+LENGTH-1
+		    READ (11'I,IOSTAT=IER) INPUT(:128)
+		    IF (IER.EQ.0) THEN
+		       CALL WRITE_BULL_FILE(NBLOCK,INPUT(:128))
+		    END IF
+		    NBLOCK = NBLOCK + 1
+		 END DO
+	      END IF
+
+	      IF (IER.EQ.0) THEN
+		 IF (MERGE) THEN
+		    CALL ADD_MERGE_FROM(IER)
+		 ELSE
+		    IF (.NOT.ORIGINAL) SYSTEM = IBSET(SYSTEM,4)
+		    CALL ADD_ENTRY	! Add the new directory entry
+		 END IF
+		 BULL_POINT = BULL_POINT + 1
+	      END IF
+	   END IF
+100	   CONTINUE
+	END DO
+
+	IF (SLIST.LT.1.AND.POST_NEWS.OR.POST_FEED) CLOSE (UNIT=3)
+
+	IF (MERGE) CALL ADD_MERGE_REST(IER)
+
+	IF (.NOT.POST_NEWS) CALL CLOSE_BULLFIL
+
+	IF (.NOT.(TO_NEWS.AND.ORIGINAL.AND.TEMP_FILE)) THEN
+	   CLOSE (UNIT=11)
+	   CLOSE (UNIT=12)
+	   TEMP_FILE = .FALSE.
+	END IF
+
+	IF (FOLDER_NUMBER.GE.0.AND.IER.EQ.0.AND..NOT.POST_NEWS
+     &		.AND.FOLDER_NUMBER.LT.FOLDER_MAX) THEN
+	   DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &			       F_NEWEST_BTIM)
+	   CALL UPDATE_FOLDER			! Update folder info
+C
+C  If user is adding message, an no new messages, update last read time for
+C  folder, so user is not alerted of new message which is owned by user.
+C
+	   IF (DIFF.GE.0) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),F_NEWEST_BTIM)
+	   END IF
+	END IF
+
+	IF (.NOT.POST_NEWS) CALL CLOSE_BULLDIR	! Totally finished with add
+
+	IF (IER.EQ.0) THEN
+	   IF (TEST_BULLCP().NE.2)
+     &	      WRITE (6,'('' Successful copy to folder '',A)')
+     &		FOLDER(:TRIM(FOLDER))//'.'
+	   IF (MERGE) THEN
+	      CALL LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &		  '.BULLDIR;-1')
+	   END IF
+	ELSE IF (MERGE) THEN
+	   WRITE (6,'('' ERROR: Copy aborted. No files copied.'')')
+	ELSE
+	   WRITE (6,'('' ERROR: Copy aborted. '',I,'' files copied.'')')
+     &			BULL_POINT - START_BULL_POINT
+	END IF
+
+	IF (.NOT.POST_NEWS) HEADER = SAVE_HEADER
+	IF (BULLCP_NEWS) RETURN
+
+	IF (INDEX(INCMD,' ').EQ.TRIM(INCMD)+1)
+     &	   INCMD = INCMD(:TRIM(INCMD))//' '//FOLDER1
+
+	FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+	FOLDER1 = SAVE_FOLDER
+	CALL SELECT_FOLDER(.FALSE.,IER1)
+
+	BULL_POINT = SAVE_BULL_POINT
+
+	IF (DELETE_ORIGINAL.AND.IER.EQ.0) THEN
+	   IF (FROM_REMOTE.AND.ALL) THEN
+	      WRITE (6,'('' WARNING: Original messages not deleted.'')')
+	      WRITE (6,'('' Multiple deletions not possible for '',
+     &			''remote folders.'')')
+	   ELSE
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL DELETE_MSG
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE PRINT(PRINT_NUM,OPEN_IT)
+C
+C  SUBROUTINE PRINT
+C
+C  FUNCTION:  Print header to queue.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SJCDEF)'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER*32 QUEUE,TEST
+
+	INTEGER*2 IOSB(4)
+	EQUIVALENCE (IOSB(1),JBC_ERROR)
+
+	CHARACTER*32 FORM
+
+	PARAMETER FF = CHAR(12)
+
+	DATA FIRST /.TRUE./, CHANGED /.FALSE./
+
+	OPENED = .FALSE.
+
+	IF (CLI$PRESENT('NOW').AND..NOT.FIRST.AND.
+     &	    INCMD(:4).EQ.'PRIN') THEN
+	   WRITE (6,'('' Printing all previously queued messages.'')')
+	   GO TO 200
+	ELSE IF (.NOT.FIRST) THEN
+	   IER = CLI$GET_VALUE('QUEUE',TEST,TLEN)
+	   CHANGED = TEST(:TLEN).NE.QUEUE(:QLEN).AND.TLEN.GT.0
+	   CHANGED = CHANGED.OR.CLI$PRESENT('NOTIFY').NE.NOTIFY
+	   IER = CLI$GET_VALUE('FORM',TEST,FLEN)
+	   CHANGED = CHANGED.OR.(TEST(:TLEN).NE.FORM(:FLEN).AND.TLEN.GT.0)
+	   IF (CHANGED) THEN
+	      WRITE (6,'('' Printing all previously queued messages.'')')
+	      GO TO 200
+	   END IF
+	END IF
+
+        IF (INCMD(:4).EQ.'PRIN') THEN
+	   IF (CLI$PRESENT('CANCEL')) THEN 
+	      WRITE (6,'('' Cancelling all previously queued messages.'')')
+	      CLOSE (UNIT=24,DISPOSE='DELETE')
+	      FIRST = .TRUE.
+	      RETURN
+	   END IF
+	END IF
+
+50	IF (PRINT_NUM.EQ.0) THEN
+	   IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	      CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+	      IF (EBULL.GT.F_NBULL) EBULL = F_NBULL
+	   ELSE IF (OPENED) THEN
+	      CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	      GO TO 150
+	   ELSE IF (CLI$PRESENT('ALL')) THEN
+	      SBULL = 1
+	      EBULL = F_NBULL
+	      IER = 0
+	   ELSE IF (BULL_POINT.EQ.0) THEN  ! No.  Have we just read a bulletin?
+	      WRITE(6,1010)		  ! No, then error.
+	      RETURN
+	   ELSE
+	      SBULL = BULL_POINT
+	      EBULL = SBULL
+	      IER = 0
+	   END IF
+	   IF (SBULL.LE.0.OR.IER.NE.0.OR.EBULL.LT.SBULL) THEN
+	      WRITE (6,1015)
+	      IF (OPENED) THEN
+		 CALL CLOSE_BULLFIL
+		 CALL CLOSE_BULLDIR
+	      END IF
+	      WRITE (6,'(1X,A)') BULL_PARAMETER(:LEN_P)
+	      RETURN
+	   END IF
+	ELSE
+	   SBULL = PRINT_NUM
+	   EBULL = SBULL
+	END IF
+
+	IF (FIRST) THEN
+	   QLEN = 0
+	   IER = CLI$GET_VALUE('QUEUE',QUEUE,QLEN) 	! Get queue name
+	   IF (QLEN.EQ.0) THEN
+	      QUEUE = 'SYS$PRINT'
+	      QLEN = TRIM(QUEUE)
+	   END IF
+
+	   NOTIFY = CLI$PRESENT('NOTIFY')
+
+	   FLEN = 0
+	   IER = CLI$GET_VALUE('FORM',FORM,FLEN)	 ! Get form name
+
+	   CALL DISABLE_PRIVS
+
+	   OPEN(UNIT=24,FILE='SYS$LOGIN:BULL.LIS',ERR=900,IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+
+	   CALL ENABLE_PRIVS
+	END IF
+
+	IF (OPEN_IT) THEN
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL OPEN_BULLFIL_SHARED
+	   OPENED = .TRUE.
+	END IF
+
+	HEAD = CLI$PRESENT('HEADER')
+
+	DO I=SBULL,EBULL
+	   I1 = I
+	   CALL READDIR(I,IER)		! Get info for specified message
+	   IF (IER.NE.I+1.OR.I.GT.EBULL.OR.(.NOT.CLI$PRESENT
+     &		('ALL').AND.I1.EQ.SBULL.AND.I.NE.SBULL)) THEN
+	      IF (REMOTE_SET.NE.3.OR.I1.EQ.SBULL) WRITE(6,1030) I1
+	      IF (I1.GT.SBULL) GO TO 100
+	      CLOSE (UNIT=24,DISPOSE='DELETE')
+	      IF (OPEN_IT) THEN
+		 CALL CLOSE_BULLFIL
+		 CALL CLOSE_BULLDIR
+	      END IF
+	      RETURN
+	   ELSE IF (REMOTE_SET) THEN
+	      CALL REMOTE_READ_MESSAGE(I,IER1)
+	      IF (IER1.GT.0) THEN
+		 CALL DISCONNECT_REMOTE
+	      ELSE
+		 CALL GET_REMOTE_MESSAGE(IER1)
+	      END IF
+	      IF (IER1.NE.0) GO TO 100
+	   END IF
+
+	   IF (.NOT.FIRST) THEN
+	      WRITE (24,'(A)') FF
+	   ELSE
+	      FIRST = .FALSE.
+	   END IF
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (HEAD) THEN
+		 WRITE(24,1060) INPUT(7:ILEN),DATE//' '//TIME(:8)
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE IF (HEAD) THEN
+	      WRITE(24,1060) FROM,DATE//' '//TIME(:8)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      IF (HEAD) WRITE(24,1050) INPUT(7:ILEN)
+	   ELSE
+	      IF (HEAD) WRITE(24,1050) DESCRIP
+	      IF (ILEN.GT.0) WRITE (24,'(A)') INPUT(:ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0) WRITE (24,'(A)') INPUT(1:ILEN)
+	   END DO
+	END DO
+
+100	IF (PRINT_NUM.EQ.0) THEN
+	   IER = OTS$CVT_L_TI(SBULL,BULL_PARAMETER,,,)
+	   IF (SBULL.EQ.EBULL) THEN
+	      WRITE(6,1040)
+     &		 BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	   ELSE
+	      WRITE(6,1045)
+     &		 BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	      IER = OTS$CVT_L_TI(EBULL,BULL_PARAMETER,,,)
+	      WRITE(6,1046)
+     &		 BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+	   END IF
+
+1040	   FORMAT(' Message ',A,' sent to printer.')
+1045	   FORMAT(' Messages ',A,$)
+1046	   FORMAT('+-',A,' sent to printer.')
+	   GO TO 50
+	ELSE IF (OPEN_IT) THEN
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	END IF
+
+150	IF (.NOT.CLI$PRESENT('NOW').OR.INCMD(:4).NE.'PRIN') RETURN
+
+	ENTRY PRINT_NOW
+
+200	IF (FIRST) RETURN
+
+	FIRST = .TRUE.
+
+	CLOSE (UNIT=24)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(18,SJC$_FILE_SPECIFICATION,
+     &		%LOC('SYS$LOGIN:BULL.LIS'))
+
+	CALL ADD_2_ITMLST(QLEN,SJC$_QUEUE,%LOC(QUEUE))
+	CALL ADD_2_ITMLST(0,SJC$_DELETE_FILE,0)
+
+	IF (NOTIFY) CALL ADD_2_ITMLST(0,SJC$_NOTIFY,0)
+
+	IF (FLEN.GT.0) THEN
+	   CALL ADD_2_ITMLST(FLEN,SJC$_FORM_NAME,%LOC(FORM))
+	END IF
+
+	CALL DISABLE_PRIVS
+
+	CALL ADD_2_ITMLST(4,SJC$_ENTRY_NUMBER_OUTPUT,%LOC(JOBNUM))
+
+	CALL END_ITMLST(SJC_ITMLST)
+
+	IER=SYS$SNDJBCW(,%VAL(SJC$_ENTER_FILE),,%VAL(SJC_ITMLST),IOSB,,)
+	IF (IER.AND.(.NOT.JBC_ERROR)) THEN
+	   CALL SYS_GETMSG(JBC_ERROR)
+	   IER = LIB$DELETE_FILE('SYS$LOGIN:BULL.LIS;')
+	ELSE IF (.NOT.IER) THEN
+	   CALL SYS_GETMSG(IER)
+	   IER = LIB$DELETE_FILE('SYS$LOGIN:BULL.LIS;')
+	ELSE
+	   IER = OTS$CVT_L_TI(JOBNUM,BULL_PARAMETER,,,)
+	   IF (IER) WRITE (6,'('' Job BULL (queue '',A,'', entry '',A,
+     &	      '') started on '',A)') QUEUE(:QLEN),
+     &	      BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):),QUEUE(:QLEN)
+	END IF
+
+	CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+
+	IF (CHANGED) THEN
+	   CHANGED = .FALSE.
+	   GO TO 50
+	END IF
+
+	RETURN
+
+900	CALL ERRSNS(IDUMMY,IER)
+	CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+	WRITE(6,1000)
+	CALL SYS_GETMSG(IER)
+	RETURN
+
+1000	FORMAT(' ERROR: Unable to open temporary file
+     &	 SYS$LOGIN:BULL.LIS for printing.')
+1010	FORMAT(' ERROR: You have not read any message.')
+1015	FORMAT(' ERROR: Specified message number has incorrect format:')
+1030	FORMAT(' ERROR: Following bulletin was not found: ',I)
+1050	FORMAT('Description: ',A,/)
+1060	FORMAT('From: ',A,/,'Date: ',A)
+
+	END
+
+
+
+
+	SUBROUTINE READ_MSG(READ_COUNT,BULL_READ)
+C
+C  SUBROUTINE READ_MSG
+C
+C  FUNCTION: Reads a specified bulletin.
+C
+C  PARAMETER:
+C	READ_COUNT - Variable to store the record in the message file
+C		that READ will read from.  Must be set to 0 to indicate
+C		that it is the first read of the message.  If -1,
+C		READ will search for the last message in the message file
+C		and read that one.  If -2, just display header information.
+C	BULL_READ - Message number to be read.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /PAGE/ PAGE_LENGTH,REAL_PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /READ_DISPLAY/ LINE_OFFSET
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /HEADER/ HEADER
+
+	COMMON /NEXT/ NEXT
+	LOGICAL NEXT /.FALSE./
+
+	COMMON /POST/ POSTTIME
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /THREAD/ THREAD
+	DATA THREAD /.FALSE./
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	DATA SCRATCH_B1/0/,LAST_THREAD/.FALSE./
+
+	CHARACTER TODAY*12,DATETIME*24,BUFFER*(INPUT_LENGTH)
+	CHARACTER HEADLINE*132
+
+	LOGICAL SINCE,PAGE
+
+	EXTERNAL CLI$_NEGATED
+
+	FIRST = BULL_READ.LT.F_START
+	KILL = BTEST(BULL_USER_CUSTOM,3)
+	BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,3)
+
+	POSTTIME = .TRUE.
+
+	CALL LIB$ERASE_PAGE(1,1)		! Clear screen
+	END = 0					! Nothing outputted on screen
+
+	IF (READ_COUNT.GT.0) GO TO 100		! Skip init steps if this is
+						! not first page of bulletin
+
+	IF (INCMD(:4).EQ.'READ'.OR.INCMD(:4).EQ.'LAST'.OR.
+     &	    INCMD(:4).EQ.'BACK'.OR.INCMD(:3).EQ.'CUR'.OR.
+     &	    INCMD(:4).EQ.'FIRS'.OR.INCMD(:1).EQ.'N') THEN
+	   IF (CLI$PRESENT('HEADER')) THEN
+	      HEADER = .TRUE.
+	   ELSE IF (CLI$PRESENT('HEADER').EQ.%LOC(CLI$_NEGATED)) THEN
+	      HEADER = .FALSE.
+	   END IF
+	   ROTC = CLI$PRESENT('ROTATE')
+	END IF
+
+	SINCE = .FALSE.
+	NEW = .FALSE.
+	PAGE = .TRUE.
+	THREAD = .FALSE.
+
+	IER = 0
+
+	IF (.NOT.PAGING) PAGE = .FALSE.
+	IF (INCMD(:4).EQ.'READ') THEN		! If READ command...
+	   POSTTIME = CLI$PRESENT('POST')
+	   THREAD = CLI$PRESENT('THREADS')
+	   IF (CLI$PRESENT('MARKED')) THEN
+	      READ_TAG = 1 + IBSET(0,1)
+	   ELSE IF (CLI$PRESENT('SEEN')) THEN
+	      READ_TAG = 1 + IBSET(0,2)
+	   ELSE IF (CLI$PRESENT('UNMARKED').OR.
+     &		   CLI$PRESENT('MARKED').EQ.%LOC(CLI$_NEGATED)) THEN
+	      READ_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+	   ELSE IF (CLI$PRESENT('UNSEEN').OR.
+     &		    CLI$PRESENT('SEEN').EQ.%LOC(CLI$_NEGATED)) THEN
+	      READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+	   ELSE IF (CLI$PRESENT('ALL')) THEN
+	      READ_TAG = IBSET(0,1) + IBSET(0,2)
+	      IF (REMOTE_SET.GE.3) THEN
+		 BULL_READ = F_START
+	      ELSE
+		 BULL_READ = 1
+	      END IF
+	   END IF
+	   IF (READ_TAG) THEN
+	      IF (.NOT.(FOLDER_NUMBER.GE.0.OR.REMOTE_SET.EQ.3)) THEN
+		 WRITE (6,'('' ERROR: Invalid qualifier'',
+     &			    '' with remote folder.'')')
+		 READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+		 GO TO 9999
+	      END IF
+	      CALL GET_FIRST_TAG(FOLDER_NUMBER,IER1,BULL_POINT)
+	   END IF
+
+	   IF (.NOT.CLI$PRESENT('PAGE')) PAGE = .FALSE.
+	   IF (CLI$PRESENT('SINCE').AND.
+     &	       .NOT.THREAD) THEN		! was /SINCE specified?
+	      IER = CLI$GET_VALUE('SINCE',DATETIME)
+	      IF (DATETIME.EQ.'TODAY') THEN	! TODAY is the default.
+		 IER = SYS$BINTIM('-- 00:00:00.00',TODAY)
+		 CALL GET_MSGKEY(TODAY,MSG_KEY)
+	      ELSE
+		 CALL SYS_BINTIM(DATETIME,MSG_BTIM)
+		 CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      END IF
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL READDIR_KEYGE(IER)
+	      CALL CLOSE_BULLDIR
+	   ELSE IF (CLI$PRESENT('NEW').OR.(THREAD.AND..NOT.
+     &		CLI$PRESENT('SINCE').AND..NOT.CLI$PRESENT('BULLETIN_NUMBER')
+     &		.AND.(.NOT.LAST_THREAD
+     &	        .OR.LAST_THREAD_NUMBER.NE.FOLDER_NUMBER)
+     &		.AND.CLI$PRESENT('NEW').NE.%LOC(CLI$_NEGATED))) THEN
+	      NEW = .TRUE.
+	      IF (REMOTE_SET.LT.3) THEN
+		 DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				 F_NEWEST_BTIM)
+		 IF (DIFF.GE.0) THEN
+		    WRITE (6,'('' No new messages are present.'')')
+		    GO TO 9999
+		 ELSE
+		    CALL GET_MSGKEY(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &							  MSG_KEY)
+		 END IF
+		 CALL OPEN_BULLDIR_SHARED
+                 IER = 0
+		 DO WHILE (IER.EQ.0)
+		    CALL READDIR_KEYGE(IER)
+	   	    IF (IER.NE.0.AND.BULL_TAG.AND.BTEST(BULL_TAG,1)) THEN
+		       CALL GET_THIS_TAG(FOLDER_NUMBER,IER1,IER,DUMMY)
+		       IF (IER1.EQ.0) THEN
+	                  CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					MSG_BTIM)
+		          CALL GET_MSGKEY(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					MSG_KEY)
+			  IER = 0
+	               END IF
+		    ELSE IF (IER.EQ.0) THEN
+		       CALL CLOSE_BULLDIR
+		       WRITE (6,'('' No more messages are present.'')')
+		       GO TO 9999
+	            END IF
+		    IF (IER.NE.0.AND.THREAD.AND..NOT.BTEST(SYSTEM,8)) THEN
+		       IER = 0
+		    END IF
+	         END DO
+		 CALL CLOSE_BULLDIR
+	      ELSE
+                 IER = 0
+		 SKIPPED_THREAD = .FALSE.
+		 IF (THREAD) CALL OPEN_BULLDIR_SHARED
+		 DO WHILE (IER.EQ.0)
+		    IF (.NOT.SKIPPED_THREAD) THEN
+		       CALL NEWS_GET_NEWEST_MESSAGE(IER)
+		       BULL_READ = IER
+		    END IF
+		    IF ((SKIPPED_THREAD.OR.(THREAD.AND.IER.NE.0)).AND.
+     &			 BULL_READ.LE.F_NBULL) THEN
+	               CALL READDIR(BULL_READ,IER)
+		       IER = IER - 1
+		       IF (IER.NE.BULL_READ) IER = 0
+		    END IF
+	   	    IF (IER.NE.0.AND.((BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)
+     &			.OR.(BULL_TAG.AND.BTEST(BULL_TAG,1)))) THEN
+		       MSG_NUM = IER
+		       CALL GET_THIS_TAG(FOLDER_NUMBER,IER1,DUMMY,DUMMY)
+		       IF (IER1.EQ.0) THEN
+	                  IF (.NOT.SKIPPED_THREAD) THEN
+		             CALL NEWS_UPDATE_NEWEST_MESSAGE(IER)
+			  ELSE
+			     BULL_READ = BULL_READ + 1
+			  END IF
+			  IER = 0
+	               END IF
+		    ELSE IF (IER.EQ.0) THEN
+		       WRITE (6,'('' No more messages are present.'')')
+		       IF (SKIPPED_THREAD) CALL CLOSE_BULLDIR
+		       GO TO 9999
+	            END IF
+		    IF (IER.NE.0.AND.THREAD.AND..NOT.BTEST(SYSTEM,8)) THEN
+		       SKIPPED_THREAD = .TRUE.
+		       BULL_READ = IER + 1
+		       IER = 0
+		    END IF
+	         END DO
+	      END IF
+	      IF (THREAD) CALL CLOSE_BULLDIR
+	      BULL_READ = IER
+	      IER = IER + 1
+	   ELSE IF (THREAD) THEN
+	      IF (CLI$PRESENT('SINCE')) THEN
+	         IF (IER.EQ.0) THEN
+		    WRITE (6,'('' No messages past specified date.'')')
+		    GO TO 9999
+	         ELSE
+		    BULL_READ = IER - 1
+		    IER = IER + 1
+	         END IF
+	         SINCE = .TRUE.
+	      ELSE IF (CLI$PRESENT('BULLETIN_NUMBER')) THEN
+		 BULL_READ = BULL_READ - 1
+	      ELSE IF (LAST_THREAD_NUMBER.EQ.FOLDER_NUMBER) THEN          
+	         BULL_READ = LAST_THREAD_READ
+	      ELSE
+	         BULL_READ = BULL_POINT - 1
+	      END IF
+	      CALL OPEN_BULLDIR_SHARED
+	      IER = BULL_READ + 1
+	      IER1 = .FALSE.
+	      DO WHILE (.NOT.IER1.AND.IER.EQ.BULL_READ+1.AND.
+     &			BULL_READ.LT.F_NBULL)
+		 BULL_READ = BULL_READ + 1
+	         CALL READDIR(BULL_READ,IER)
+		 IER1 = BTEST(SYSTEM,8)
+	   	 IF (IER1.AND.((BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)
+     &			.OR.(BULL_TAG.AND.BTEST(BULL_TAG,1)))) THEN
+		    CALL GET_THIS_TAG(FOLDER_NUMBER,IER2,DUMMY,DUMMY)
+		    IER1 = IER2.NE.0
+		 END IF
+	      END DO
+	      IF (.NOT.IER1) THEN
+		 WRITE (6,'('' No more messages are present.'')')
+		 GO TO 9999
+	      END IF
+	   END IF
+	END IF
+
+	NEXT = .FALSE.
+	LAST_THREAD = .FALSE.
+	IF (INCMD(:1).EQ.'N'.OR.INCMD.EQ.' ') THEN
+	   NEXT = .TRUE.
+	ELSE IF (INCMD(:4).EQ.'READ') THEN
+	   LAST_THREAD = THREAD
+	   IF (THREAD) THEN
+	      LAST_THREAD_READ = BULL_READ
+	      LAST_THREAD_NUMBER = FOLDER_NUMBER
+	   ELSE
+	      IF (.NOT.SINCE.AND..NOT.NEW
+     &		 .AND..NOT.CLI$PRESENT('BULLETIN_NUMBER')
+     &		 .AND..NOT.CLI$PRESENT('ALL')) NEXT = .TRUE.
+	   END IF
+	END IF
+
+	BULL_NOW = BULL_POINT
+
+	OK = .TRUE.
+50	IF (READ_TAG) THEN
+	   IER = 0
+	   IF ((INCMD(:4).EQ.'BACK'.AND.REMOTE_SET.GE.3).OR.
+     &	       (INCMD(:4).EQ.'LAST'.AND.BTEST(READ_TAG,3))) THEN
+	      IF (BULL_NOW.EQ.0.OR.INCMD(:4).EQ.'LAST') THEN
+		 MSG_NUM = F_NBULL+1
+	      ELSE
+		 MSG_NUM = BULL_NOW
+	      END IF
+	      CALL GET_PREVIOUS_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      IF (IER1.EQ.0) IER = BULL_READ + 1
+	   ELSE IF (INCMD(:4).EQ.'BACK') THEN
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL GET_PREVIOUS_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      CALL CLOSE_BULLDIR
+	      IF (IER1.EQ.0) IER = BULL_READ + 1
+	   ELSE IF (INCMD(:4).EQ.'LAST') THEN
+	      CALL OPEN_BULLDIR_SHARED
+	      IF (BULL_NOW.GT.0) THEN
+		 CALL READDIR(BULL_NOW,IER)
+		 IF (IER.NE.BULL_NOW+1) THEN
+		    BULL_NOW = 0
+		 ELSE
+		    CALL GET_THIS_OR_NEXT_TAG
+     &				   (FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		    IF (IER1.NE.0) BULL_NOW = 0
+		 END IF
+	      END IF
+	      IF (BULL_NOW.EQ.0) THEN
+		 CALL GET_FIRST_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		 IF (IER1.EQ.0) IER = BULL_READ + 1
+	      END IF
+	      DO WHILE (IER1.EQ.0)
+		 CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		 IF (IER1.EQ.0) IER = BULL_READ + 1
+	      END DO
+	      CALL CLOSE_BULLDIR
+	   ELSE IF (INCMD(:4).EQ.'FIRS') THEN
+	      CALL GET_FIRST_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      IF (IER1.EQ.0) IER = BULL_READ + 1
+	   ELSE IF (NEXT.OR.SINCE.OR.NEW) THEN
+	      OLD_NEXT = NEXT
+	      NEXT = .FALSE.
+	      IF (NEW) MSG_NUM = BULL_READ
+	      IF (.NOT.OLD_NEXT) THEN
+		 CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      ELSE
+		 IF (REMOTE_SET.GE.3) THEN
+		    MSG_NUM = BULL_NOW
+		 ELSE IF (BULL_NOW.GT.0) THEN
+		    CALL OPEN_BULLDIR_SHARED
+		    CALL READDIR(BULL_NOW,IER)
+		    CALL CLOSE_BULLDIR
+		 ELSE
+		    MSG_KEY = BULLDIR_HEADER
+		    MSG_NUM = 0
+		 END IF
+		 CALL GET_NEXT_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+	      END IF
+	      NEXT = OLD_NEXT
+	      IF (IER1.EQ.0) THEN
+		 IER = BULL_READ + 1
+	      ELSE
+		 IER = 0
+	      END IF
+	   END IF
+	END IF
+
+	IF (.NOT.SINCE.AND.(.NOT.READ_TAG.OR.(.NOT.NEXT.AND.
+     &		INCMD(:4).NE.'LAST'.AND.INCMD(:4).NE.'BACK'.AND.
+     &		INCMD(:4).NE.'FIRS'))) THEN
+	   IF (BULL_READ.GT.0) THEN		! Valid bulletin number?
+	      CALL OPEN_BULLDIR_SHARED
+	      CALL READDIR(BULL_READ,IER)	! Get bulletin directory entry
+	      IF (IER.NE.BULL_READ+1.AND.REMOTE_SET.GE.3
+     &			   .AND.INCMD(:4).EQ.'READ') THEN
+		 IF (NEW) THEN
+		    NEXT = .TRUE.
+		    CALL READDIR(BULL_READ,IER)
+		 END IF
+	      END IF
+	      IF (REMOTE_SET.LT.3.AND.
+     &			   READ_COUNT.EQ.-1.AND.IER.NE.BULL_READ+1) THEN
+		 READ_COUNT = 0
+		 IF (IER.NE.BULL_READ+1) THEN
+		    CALL READDIR(0,IER)
+		    IF (NBULL.GT.0) THEN
+		       BULL_READ = NBULL
+		       CALL READDIR(BULL_READ,IER)
+		    ELSE
+		       IER = 0
+		    END IF
+		 END IF
+	      ELSE IF (READ_TAG.AND.IER.EQ.BULL_READ+1) THEN
+		 CALL GET_THIS_TAG(FOLDER_NUMBER,IER1,BULL_READ,DUMMY)
+		 IF (IER1.NE.0) IER = 0
+	      END IF
+	      CALL CLOSE_BULLDIR
+	   ELSE
+	      IER = 0
+	   END IF
+	END IF
+
+	IF (IER.NE.BULL_READ+1) THEN		! Was bulletin found?
+	   IF (REMOTE_SET.LT.3) THEN
+	      WRITE(6,1030)			! If not, then error out
+	   ELSE
+	      WRITE(6,1040)
+	   END IF
+	   NEXT = .FALSE.
+	   IF (.NOT.OK.AND..NOT.REMOTE_SET) CALL CLOSE_BULLFIL
+	   GO TO 9999
+	END IF
+
+	SAVE_BULL_POINT = BULL_POINT
+	BULL_POINT = BULL_READ			! Update bulletin counter
+
+	IF (OK.OR.REMOTE_SET) CALL OPEN_BULLFIL_SHARED
+
+	IF (BTEST(BULL_USER_CUSTOM,1)
+     &		.AND.(FIRST.OR.NEW.OR.NEXT.OR.INCMD(:4).EQ.'BACK'.OR.
+     &		INCMD(:4).EQ.'LAST'.OR.INCMD(:4).EQ.'FIRS')) THEN
+	   ILEN = LINE_LENGTH + 1
+	   BLOCK_SAVE = BLOCK
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      INFROM = INPUT(7:ILEN)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE
+	      INFROM = FROM
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      INDESCRIP = INPUT(7:ILEN)
+	   ELSE
+	      INDESCRIP = DESCRIP
+	   END IF
+
+	   OK = INCLUDE_MSG(INFROM,INDESCRIP)
+	   OK = OK.AND.(.NOT.THREAD.OR.BTEST(SYSTEM,8)) 
+
+	   IF (.NOT.OK) THEN
+	      BULL_POINT = SAVE_BULL_POINT
+	      BULL_NOW = MSG_NUM
+	      IF (INCMD(:4).EQ.'BACK'.OR.INCMD(:4).EQ.'LAST') THEN
+	         BULL_READ = MSG_NUM - 1
+	      ELSE
+	         BULL_READ = MSG_NUM + 1
+		 IF (INCMD(:4).EQ.'FIRS'.OR.FIRST) NEXT = .TRUE.
+	      END IF
+	      IF (REMOTE_SET) CALL CLOSE_BULLFIL
+	      IF (REMOTE_SET.LT.3.AND..NOT.THREAD) THEN
+		 DIFF = COMPARE_BTIM(MSG_BTIM,
+     &				LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	         IF (DIFF.GT.0) THEN
+	            CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+	         END IF
+	      ELSE IF (.NOT.THREAD) THEN
+	         CALL NEWS_UPDATE_NEWEST_MESSAGE(BULL_NOW)
+              END IF
+	      IF (BULL_READ.GT.F_NBULL.OR.BULL_READ.LT.F_START) THEN
+		 IF (REMOTE_SET.LT.3) THEN
+	            WRITE(6,1030)
+	         ELSE
+		    WRITE(6,1040)
+		 END IF
+		 NEXT = .FALSE.
+	         IF (.NOT.REMOTE_SET) CALL CLOSE_BULLFIL
+		 GO TO 9999
+	      END IF
+	      GO TO 50
+	   END IF
+	   BLOCK = BLOCK_SAVE
+	END IF
+
+	NEXT = .FALSE.
+	IF (REMOTE_SET.LT.3.AND..NOT.THREAD) THEN
+           IF (INCMD(:4).NE.'SEAR'.AND.INCMD(:3).NE.'CUR') THEN
+	      DIFF = COMPARE_BTIM(MSG_BTIM,LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+	      IF (DIFF.GT.0) THEN
+	         CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+	      END IF
+	   END IF
+	   IF (BULL_TAG.AND.BTEST(BULL_TAG,1)) CALL ADD_TAG(IER,2)
+	   IF (INCMD.EQ.'LAST'.AND..NOT.READ_TAG) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),F_NEWEST_BTIM)
+	   END IF
+	ELSE
+	   IF (REMOTE_SET.EQ.4) MESSAGE_ID = NEWS_MSGID
+	   IF (BULL_NEWS_TAG) CALL ADD_TAG(IER,2)
+	   IF (.NOT.THREAD.OR.INCMD(:4).NE.'READ') THEN 
+	      IF (INCMD.EQ.'LAST'.AND..NOT.READ_TAG) THEN
+	         CALL NEWS_UPDATE_NEWEST_MESSAGE(F_NBULL)
+	      END IF
+	      IF (INCMD(:4).NE.'SEAR'.AND.INCMD(:3).NE.'CUR') THEN
+	         CALL NEWS_UPDATE_NEWEST_MESSAGE(BULL_READ)
+	      ELSE
+	         CALL NEWS_GET_NEWEST_MESSAGE(IER)
+	         IF (IER.EQ.BULL_READ)
+     &		    CALL NEWS_UPDATE_NEWEST_MESSAGE(BULL_READ)
+	      END IF
+	   END IF
+	END IF
+
+	EDIT = .FALSE.
+
+	PAGE_WIDTH = REAL_PAGE_WIDTH
+
+	IF (INCMD(:1).NE.' '.AND.READIT.EQ.0) THEN
+	   IF (CLI$PRESENT('EDIT')) THEN
+	      OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      IF (IER.NE.0) THEN
+		 CALL ERRSNS(IDUMMY,IER)
+		 CALL SYS_GETMSG(IER)
+		 GO TO 9999
+	      END IF
+	      EDIT = .TRUE.
+	      PAGE_WIDTH = LINE_LENGTH
+	      PAGE = .FALSE.
+	   END IF
+	END IF
+
+	IF (BULL_POINT.GT.F_NBULL) F_NBULL = BULL_POINT
+
+	IF (REMOTE_SET.GE.3) THEN
+	   WRITE (HEADLINE,'(1X,I,'' of '',I,''-'',I)')
+     &				BULL_POINT,F_START,F_NBULL
+	   DO WHILE (INDEX(HEADLINE,'- ').GT.0)
+	      I = INDEX(HEADLINE,'- ')
+	      HEADLINE(I+1:) = HEADLINE(I+2:)
+	   END DO
+	ELSE
+	   WRITE (HEADLINE,'(1X,I,'' of '',I)') BULL_POINT,F_NBULL
+	END IF
+	DO WHILE (INDEX(HEADLINE,'  ').LT.TRIM(HEADLINE))
+	   I = INDEX(HEADLINE,'  ')
+	   HEADLINE(I:) = HEADLINE(I+1:)
+	END DO
+	I = TRIM(HEADLINE)
+	HEADLINE = ' #'//HEADLINE(2:TRIM(HEADLINE))
+	FLEN = TRIM(FOLDER_NAME)
+	HEADLINE(REAL_PAGE_WIDTH-FLEN+1:) = FOLDER_NAME(:FLEN)
+	IF (READIT.GT.0) THEN
+	   WRITE(6,'(A)') '+'//HEADLINE(:TRIM(HEADLINE))
+	ELSE IF (EDIT) THEN
+	   WRITE(3,'(A)') HEADLINE(:TRIM(HEADLINE))
+	ELSE
+	   WRITE(6,'(1X,A)') HEADLINE(:TRIM(HEADLINE))
+	END IF
+
+	END = 1					! Outputted 1 line to screen
+
+	IF (EXDATE(8:11).LT.'1995') THEN
+	   IF (REMOTE_SET.NE.3) THEN
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   (DELETED)'
+	   ELSE
+	      INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+	   END IF
+	ELSE IF ((SYSTEM.AND.4).EQ.4) THEN	! Is entry shutdown bulletin?
+	   INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Expires on shutdown'
+	ELSE IF ((SYSTEM.AND.2).EQ.2) THEN	! Is entry permanent bulletin?
+	   INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)
+     &				//'   Permanent'
+	ELSE
+	   INPUT = 'Date:   '//DATE(:TRIM(DATE))//' '//TIME(:5)//
+     &				'   Expires:   '//EXDATE//' '//EXTIME(:5)
+	END IF
+	IF ((SYSTEM.AND.1).EQ.1) THEN		! System bulletin?
+	   INPUT = INPUT(:TRIM(INPUT))//' / System'
+	END IF
+	IF (EDIT) THEN
+	   WRITE (3,'(A)') INPUT(:TRIM(INPUT))
+	ELSE
+	   WRITE (6,'(1X,A)') INPUT(:TRIM(INPUT))
+	END IF
+
+	END = END + 1
+
+	LINE_OFFSET = 0
+	CHAR_OFFSET = 0
+	ILEN = LINE_LENGTH + 1
+	CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: '
+     &	   .AND..NOT.BTEST(SYSTEM,4)) THEN
+	   INPUT = 'From:   '//INPUT(7:)
+	   DO WHILE (TRIM(INPUT).GT.0)
+	      I = MIN(PAGE_WIDTH,TRIM(INPUT))
+	      IF (EDIT) THEN
+		 WRITE(3,'(A)') INPUT(:I)
+	      ELSE
+		 WRITE(6,'(1X,A)') INPUT(:I)
+	      END IF
+	      INPUT = INPUT(I+1:)
+	      END = END + 1
+	   END DO
+	   LINE_OFFSET = 1
+	ELSE
+	   IF (EDIT) THEN
+	      WRITE(3,'(''From:   '',A)') FROM
+	   ELSE
+	      WRITE(6,'('' From:   '',A)') FROM
+	   END IF
+	   END = END + 1
+	END IF
+	IF (INPUT(:6).NE.'Subj: ') THEN
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	END IF
+	LEN_TEMP = ILEN
+	CALL CONVERT_TABS(INPUT,LEN_TEMP)
+	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	   INPUT = 'Subj:   '//INPUT(7:)
+	   DO WHILE (TRIM(INPUT).GT.0)
+	      I = MIN(PAGE_WIDTH,TRIM(INPUT))
+	      IF (EDIT) THEN
+		 WRITE(3,'(A)') INPUT(:I)
+	      ELSE
+		 WRITE(6,'(1X,A)') INPUT(:I)
+	      END IF
+	      INPUT = INPUT(I+1:)
+	      END = END + 1
+	   END DO
+	   LINE_OFFSET = LINE_OFFSET + 1
+	   IF (EDIT) WRITE(3,'(1X)')
+	ELSE
+	   END = END + 1
+	   IF (EDIT) THEN
+	      WRITE(3,'(''Subj:   '',A)') DESCRIP(:TRIM(DESCRIP))
+	      WRITE(3,'(1X,/,A)') INPUT(:LEN_TEMP)
+	   ELSE
+	      WRITE(6,'('' Subj:   '',A)') DESCRIP(:TRIM(DESCRIP))
+	      IF (LINE_OFFSET.EQ.1) THEN
+		 CHAR_OFFSET = 1 - PAGE_WIDTH
+		 LINE_OFFSET = 2
+		 IF (ROTC) CALL CONVERT_ROTC(INPUT,LEN_TEMP)
+	      END IF
+	   END IF
+	END IF
+	IF (LINE_OFFSET.EQ.0) ILEN = LINE_LENGTH + 1
+	CALL CLOSE_BULLFIL			! End of bulletin file read
+
+	IF (EDIT) GO TO 200
+
+	WRITE(6,'(1X)')
+
+	IF (READIT.GT.0) WRITE(6,'(1X)')
+	END = END + 1
+C
+C  Each page of the bulletin is buffered into temporary memory storage before
+C  being outputted to the terminal.  This is to be able to quickly close the
+C  bulletin file, and to avoid the possibility of the user holding the screen,
+C  and thus causing the bulletin file to stay open.  The temporary memory
+C  is structured as a linked-list queue, where SCRATCH_B1 points to the header
+C  of the queue.  See BULLSUBS.FOR for more description of the queue.
+C
+
+	IF (SCRATCH_B1.NE.0) THEN		! Is queue empty?
+	   SCRATCH_B = SCRATCH_B1		! No, set queue pointer to head
+	ELSE					! Else if queue is empty
+	   CALL INIT_QUEUE(SCRATCH_B,INPUT)
+	   SCRATCH_B1 = SCRATCH_B		! Init header pointer
+	END IF
+
+	READ_ALREADY = 0			! Number of lines already read
+						! from record.
+	IF (READ_COUNT.EQ.-2) THEN		! Just output header first read
+	   READ_COUNT = BLOCK
+	   GO TO 9999
+	ELSE
+	   READ_COUNT = BLOCK			! Init bulletin record counter
+	END IF
+
+	GO TO 200
+
+100	IF (READIT.EQ.0) THEN 			! If not 1st page of READ
+	   WRITE(6,'(1X,A,/)') HEADLINE(:TRIM(HEADLINE)) ! Output header info
+	   END = END + 2			! Increase display counter
+	END IF
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+
+200	DISPLAY = 0
+	IF (READIT.GT.0) END = END - 2		! /READ can output 2 more lines
+
+	CALL OPEN_BULLFIL_SHARED		! Get bulletin file
+	MORE_LINES = .TRUE.
+	DO WHILE (ILEN.GT.0.AND.MORE_LINES)
+	   IF (CHAR_OFFSET.EQ.0) THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      LINE_OFFSET = LINE_OFFSET + 1
+	   END IF
+	   IF (ILEN.LT.0) THEN		! Error, couldn't read record
+	      ILEN = 0			! Fake end of reading file
+	      MORE_LINES = .FALSE.
+	   ELSE IF (ILEN.GT.0) THEN
+	      IF (EDIT) THEN
+		 WRITE(3,'(A)') INPUT(:ILEN)
+	      ELSE IF (CHAR_OFFSET.EQ.0) THEN
+		 LEN_TEMP = ILEN
+		 CALL CONVERT_TABS(INPUT,LEN_TEMP)
+		 IF (ROTC) CALL CONVERT_ROTC(INPUT,LEN_TEMP)
+		 IF (LEN_TEMP.GT.PAGE_WIDTH) THEN
+		    CHAR_OFFSET = 1
+		    BUFFER = INPUT(:PAGE_WIDTH)
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER)
+		 ELSE
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,INPUT)
+		 END IF
+	      ELSE
+		 CHAR_OFFSET = CHAR_OFFSET + PAGE_WIDTH
+		 IF (LEN_TEMP.LE.CHAR_OFFSET+PAGE_WIDTH-1) THEN
+		    BUFFER = INPUT(CHAR_OFFSET:LEN_TEMP)
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER)
+		    CHAR_OFFSET = 0
+		 ELSE
+		    BUFFER = INPUT(CHAR_OFFSET:CHAR_OFFSET+PAGE_WIDTH-1)
+		    CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER)
+		 END IF
+	      END IF
+	      DISPLAY = DISPLAY + 1
+	      IF ((DISPLAY.EQ.PAGE_LENGTH-END-4).AND.PAGE) THEN
+		 MORE_LINES = .FALSE.
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFIL			! End of bulletin file read
+
+	IF (EDIT) THEN
+	   CLOSE (UNIT=3)
+	   CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	   READ_COUNT = 0			! init bulletin record counter
+	   GO TO 9999
+	END IF
+
+C
+C  Bulletin page is now in temporary memory, so output to terminal.
+C  Note that if this is a /READ, the first line will have problems with
+C  the usual FORMAT statement.  It will cause a blank line to be outputted
+C  at the top of the screen.  This is because of the input QIO at the
+C  end of the previous page.  The output gets confused and thinks it must
+C  end the previous line.  To prevent that, the first line of a new page
+C  in a /READ must use a different FORMAT statement to surpress the CR/LF.
+C
+
+	SCRATCH_B = SCRATCH_B1			! Reinit queue pointer to head
+	DO I=1,DISPLAY				! Output page to terminal
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,BUFFER) ! Get queue record
+	   IF (I.EQ.1.AND.READIT.GT.0) THEN
+	      WRITE(6,'(A)') '+'//BUFFER(:TRIM(BUFFER))	 ! (See above comments)
+	   ELSE
+	      WRITE(6,'(1X,A)') BUFFER(:TRIM(BUFFER))
+	   END IF
+	END DO
+
+	IF (ILEN.EQ.0) THEN			! End of message?
+	   READ_COUNT = 0			! init bulletin record counter
+	ELSE	! Possibly end of message since end of page could be last line
+	   CALL TEST_MORE_RECORDS(BLOCK,LENGTH,IREC)
+	   IF (IREC.EQ.0) THEN			! Last record?
+	      CALL TEST_MORE_LINES(ILEN)	! More lines to read?
+	      IF (ILEN.GT.0) THEN		! Yes, there are still more
+		 IF (READIT.EQ.0) WRITE(6,1070)	! say there is more of bulletin
+	      ELSE				! Yes, last line anyway
+		 READ_COUNT = 0			! init bulletin record counter
+	      END IF
+	   ELSE IF (READIT.EQ.0) THEN		! Not last record so
+	      WRITE(6,1070)			! say there is more of bulletin
+	   END IF
+	END IF
+
+9999	POSTTIME = .FALSE.
+	IF (KILL) BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,3)
+	RETURN
+
+1030	FORMAT(' No more messages.')
+1040	FORMAT(' Message not found.')
+1070	FORMAT(1X,/,' Press RETURN for more...',/)
+
+2000	FORMAT(A)
+
+	END
+
+
+
+
+
+	SUBROUTINE CONVERT_ROTC(INPUT,LEN_TEMP)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER INPUT*(*)
+
+	DO I=1,LEN_TEMP
+	   IF (INPUT(I:I).GE.'A'.AND.INPUT(I:I).LE.'Z') THEN
+	      INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) - 13)
+	      IF (INPUT(I:I).LT.'A')
+     &			INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) + 26)
+	   ELSE IF (INPUT(I:I).GE.'a'.AND.INPUT(I:I).LE.'z') THEN
+	      INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) - 13)
+	      IF (INPUT(I:I).LT.'a')
+     &			INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) + 26)
+
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+
+
+	SUBROUTINE READNEW(REDO)
+C
+C  SUBROUTINE READNEW
+C
+C  FUNCTION: Displays new non-system bulletins with prompts between bulletins.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /READ_DISPLAY/ LINE_OFFSET
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER INREAD4*4,FILE_DEF*80,NUMREAD*8
+	CHARACTER INREAD*1
+	EQUIVALENCE (INREAD4,INREAD)
+
+	DATA LEN_FILE_DEF /0/, INREAD/0/
+
+	LOGICAL SLOW,SLOW_TERMINAL
+
+	FIRST_MESSAGE = BULL_POINT
+
+	IF (ICHAR(INREAD).EQ.0) THEN	! If calling READNEW for first time
+	   SLOW = SLOW_TERMINAL()	! Check baud rate of terminal
+	END IF				! to avoid gobs of output
+
+	LEN_P = 0			! Tells read subroutine there is
+					! no bulletin parameter
+
+1	WRITE(6,1000)			! Ask if want to read new bulletins
+
+	CALL GET_INPUT_NUM(NUMREAD,NLEN)	! Get input
+	CALL STR$UPCASE(NUMREAD,NUMREAD)	! Make input upper case
+	READ (NUMREAD,'(I<NLEN>)',IOSTAT=IER) TEMP_READ
+	IF (IER.NE.0) THEN
+	   INREAD = NUMREAD(:1)
+	   IF (INREAD.EQ.'N'.OR.INREAD.EQ.'Q'.OR.INREAD.EQ.'E') THEN
+	      IF (INREAD.EQ.'Q') THEN
+		 WRITE (6,'(''+uit'',$)')
+	      ELSE IF (INREAD.EQ.'E') THEN
+		 WRITE (6,'(''+xit'',$)')
+		 DO I=1,FLONG			! Just show SYSTEM folders
+		    NEW_MSG(I) = NEW_MSG(I).AND.SYSTEM_FLAG(I)
+		 END DO
+		 DO I=1,FLONG	! Test for new messages in SYSTEM folders
+		    IF (NEW_MSG(I).NE.0) RETURN
+		 END DO
+		 CALL EXIT
+	      ELSE
+		 WRITE (6,'(''+o'',$)')
+	      END IF
+	      RETURN	! If NO, exit
+	      		! Include QUIT to be consistent with next question
+	   ELSE
+	      CALL LIB$ERASE_PAGE(1,1)
+	   END IF
+	END IF
+
+3	IF (TEMP_READ.GT.0) THEN
+	   IF (TEMP_READ.LT.FIRST_MESSAGE+1.OR.TEMP_READ.GT.NBULL) THEN
+	      WRITE (6,'('' ERROR: Specified new message not found.'')')
+	      GO TO 1
+	   ELSE
+	      BULL_POINT = TEMP_READ - 1
+	   END IF
+	END IF
+
+	READ_COUNT = 0				! Initialize display pointer
+
+5	CALL READ_MSG(READ_COUNT,BULL_POINT+1)	! Read next bulletin
+	BULL_POINT_READ = BULL_POINT
+	IF (READ_COUNT.EQ.0) THEN		! Is full bulletin displayed?
+	   CALL OPEN_BULLDIR_SHARED		! If so, see if more new bulls
+10	   CALL READDIR(BULL_POINT+1,IER_POINT)
+	   IF ((IER_POINT.EQ.BULL_POINT+2).AND.	! If system bulletin (and system
+     &	       (SYSTEM.AND.BTEST(FOLDER_FLAG,2))) THEN	! folder) then skip it.
+	      BULL_POINT = BULL_POINT + 1
+	      GO TO 10
+	   END IF
+	   CALL CLOSE_BULLDIR
+	END IF
+
+	GO TO 12
+
+11	IF (READ_COUNT.GT.0) THEN
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL OPEN_BULLFIL_SHARED
+	   CALL READDIR(BULL_POINT,IER)
+	   ILEN = LINE_LENGTH+1
+	   DO I=1,LINE_OFFSET
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END DO
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	END IF
+
+	BULL_POINT = BULL_POINT_SAVE
+	LENGTH = LENGTH_SAVE
+	BLOCK = BLOCK_SAVE
+
+12	IF (READ_COUNT.EQ.0) THEN		! Prompt user in between
+	   WRITE(6,1020)			! full screens or end of bull.
+	ELSE
+	   WRITE(6,1030)
+	END IF
+
+	CALL GET_INPUT_NOECHO(INREAD)
+	CALL STR$UPCASE(INREAD,INREAD)	! Convert input to upper case
+
+	BLOCK_SAVE = BLOCK
+	LENGTH_SAVE = LENGTH
+	BULL_POINT_SAVE = BULL_POINT
+
+	IF (INREAD.EQ.'Q') THEN		! If Q , then QUIT
+	   WRITE (6,'(''+Quit'',$)')
+	   RETURN
+	ELSE IF (INREAD.EQ.'D') THEN	! If D , then redisplay directory
+	   WRITE (6,'(''+Dir'',$)')
+	   REDO = .TRUE.
+	   RETURN
+	ELSE IF (INREAD.EQ.'F'.AND..NOT.CAPTIVE(1)) THEN
+	   				! If F then copy bulletin to file
+	   WRITE (6,'(''+ '')')		! Move cursor from end of prompt line
+	   				! to beginning of next line.
+	   IF (LEN_FILE_DEF.EQ.0) THEN
+	      CALL LIB$SYS_TRNLOG('SYS$LOGIN',ILEN,FILE_DEF)
+	      IER = LIB$FIND_FILE(FILE_DEF//'BULL.DIR',
+     &			BULL_PARAMETER,CONTEXT)
+	      IF (IER) THEN
+		 FILE_DEF = BULL_PARAMETER(:ILEN-1)//'.BULL]'
+		 LEN_FILE_DEF = ILEN + 5
+	      ELSE
+		 FILE_DEF = 'SYS$LOGIN:'
+		 LEN_FILE_DEF = 10
+	      END IF
+	   END IF
+
+	   LEN_FOLDER = TRIM(FOLDER)
+	   CALL GET_INPUT_PROMPT(BULL_PARAMETER,LEN_P,
+     &		'Name of file? (Default='//FILE_DEF(:LEN_FILE_DEF)//
+     &		FOLDER(:LEN_FOLDER)//'.LIS) ')
+
+	   IF (LEN_P.EQ.0) THEN
+	      BULL_PARAMETER = FILE_DEF(:LEN_FILE_DEF)//FOLDER(:LEN_FOLDER)
+     &			//'.LIS'
+	      LEN_P = LEN_FILE_DEF + LEN_FOLDER + 4
+	   ELSE
+	      IER = LIB$SYS_TRNLOG(BULL_PARAMETER(:LEN_P),ILEN,INPUT)
+	      IF (IER.NE.1.AND.INDEX(BULL_PARAMETER(:LEN_P),':').EQ.0
+     &		  .AND.INDEX(BULL_PARAMETER(:LEN_P),'[').EQ.0) THEN
+		 BULL_PARAMETER = FILE_DEF(:LEN_FILE_DEF)//
+     &				BULL_PARAMETER(:LEN_P)
+		 LEN_P = LEN_P + LEN_FILE_DEF
+	      END IF
+	   END IF
+
+	   BULL_POINT = BULL_POINT_READ
+	   INCMD = 'FILE '//BULL_PARAMETER(:LEN_P)
+	   IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	   CALL FILE(0,.TRUE.,.FALSE.)
+	   GO TO 11
+	ELSE IF (INREAD.EQ.'P') THEN
+	   WRITE (6,'(''+P'',$)')
+	   BULL_POINT = BULL_POINT_READ
+	   IF (REMOTE_SET.GE.3.OR.
+     &	       INDEX(FOLDER_DESCRIP,'<').GT.0) THEN
+	      WRITE(6,1040)
+	      CALL GET_INPUT_NOECHO(INREAD)
+	      CALL STR$UPCASE(INREAD,INREAD)
+	      IF (INREAD.EQ.'P') THEN
+		 WRITE (6,'(''+P'',$)')
+		 INCMD = 'REPLY'
+	      ELSE IF (INREAD.EQ.'U') THEN
+		 WRITE (6,'(''+U'',$)')
+		 INCMD = 'RESPOND'
+	      ELSE IF (INREAD.EQ.'B') THEN
+		 WRITE (6,'(''+B'',$)')
+		 INCMD = 'RESPOND/LIST'
+	      ELSE
+		 GO TO 11
+	      END IF
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL RESPOND
+	   ELSE IF (READ_ONLY) THEN
+	      WRITE (6,'(
+     &		 '' ERROR: You do not write access to this folder.'')')
+	   ELSE
+	      INCMD = 'REPLY'
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL REPLY
+	   END IF
+	   GO TO 11
+	ELSE IF (INREAD.EQ.'N'.AND.READ_COUNT.GT.0) THEN
+	   			! If NEXT and last bulletins not finished
+	   READ_COUNT = 0			! Reset read bulletin counter
+	   CALL OPEN_BULLDIR_SHARED		! Look for NEXT bulletin
+20	   CALL READDIR(BULL_POINT+1,IER)
+	   IF (IER.NE.BULL_POINT+2) THEN	! If no NEXT bulletin
+	      CALL CLOSE_BULLDIR		! Exit
+	      WRITE(6,1010)
+	      RETURN
+	   ELSE IF (SYSTEM.AND.BTEST(FOLDER_FLAG,2)) THEN
+	      BULL_POINT = BULL_POINT + 1	! If SYSTEM bulletin, skip it
+	      GO TO 20			! Look for more bulletins
+	   END IF
+	   CALL CLOSE_BULLDIR
+	ELSE IF (INREAD.EQ.'R') THEN
+	   WRITE (6,'(''+Read'')')
+	   WRITE (6,'('' Enter message number: '',$)')
+	   CALL GET_INPUT_NUM(NUMREAD,NLEN)	! Get input
+	   CALL STR$UPCASE(NUMREAD,NUMREAD)	! Make input upper case
+	   READ (NUMREAD,'(I<NLEN>)',IOSTAT=IER) TEMP_READ
+	   IF (IER.NE.0.OR.TEMP_READ.LE.0) THEN
+	      WRITE (6,'('' ERROR: Invalid message number specified.'')')
+	      GO TO 12
+	   ELSE
+	      GO TO 3
+	   END IF
+	ELSE IF (IER_POINT.NE.BULL_POINT+2.AND.READ_COUNT.EQ.0) THEN
+	   WRITE(6,1010)
+	   RETURN
+	END IF
+	IF (READ_COUNT.EQ.0.AND.SLOW) READ_COUNT = -2
+	GO TO 5
+
+1000	FORMAT(' Read messages? Type N(No),E(Exit),message',
+     &	 ' number, or any other key for yes: ',$)
+1010	FORMAT(' No more messages.')
+1020	FORMAT(1X,<PAGE_WIDTH>('-'),/,' Type Q(Quit),F(File),D(Dir),',
+     &	'R(Read msg #),P(Reply) or other for next message: ',$)
+1030	FORMAT(1X,<PAGE_WIDTH>('-'),/,' Type Q(Quit),F(File),N(Next),',
+     &	'D(Dir),R(Read msg #),P(Reply) or other for MORE: ',$)
+1040	FORMAT(' Type P to post reply, U to reply to user,',
+     &	' B to do both, or other to quit: ',$)
+
+	END
+
+
+
+
+	SUBROUTINE SET_DEFAULT_EXPIRE
+C
+C  SUBROUTINE SET_DEFAULT_EXPIRE
+C
+C  FUNCTION: Sets default expiration date.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER EXPIRE*3
+
+	IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   IER = CLI$GET_VALUE('DEFAULT_EXPIRE',EXPIRE,EX_LEN)
+	   IF (EX_LEN.GT.3) EX_LEN = 3
+	   READ (EXPIRE,'(I<EX_LEN>)') TEMP
+
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   IF (TEMP.GT.BBEXPIRE_LIMIT.AND..NOT.SETPRV_PRIV()) THEN
+	      WRITE (6,'('' ERROR: Expiration cannot be > '',
+     &			I3,'' days.'')') BBEXPIRE_LIMIT
+	   ELSE IF (TEMP.LT.-1) THEN
+	      WRITE (6,'('' ERROR: Expiration must be > -1.'')')
+	   ELSE
+	      FOLDER_BBEXPIRE = TEMP
+	      WRITE (6,'('' Default expiration modified.'')')
+	   END IF
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLFOLDER
+	ELSE
+	   WRITE (6,'('' You are not authorized to set expiration.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION NEWS_FEED()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	NEWS_FEED = .FALSE.
+
+	SLIST = INDEX(FOLDER_DESCRIP,'<')
+	IF (SLIST.GT.0) THEN
+	   I = SLIST + 1
+	   FLEN = TRIM(FOLDER_DESCRIP)
+	   DO WHILE (I.LE.FLEN)
+	      IF (FOLDER_DESCRIP(I:I).EQ.'>') THEN
+		 IF (INDEX(FOLDER_DESCRIP(SLIST:I),'.').GT.0)
+     &		    NEWS_FEED = .TRUE.
+		 RETURN
+	      ELSE IF ((FOLDER_DESCRIP(I:I).LT.'A'.OR.
+     &		  FOLDER_DESCRIP(I:I).GT.'Z').AND.
+     &		  FOLDER_DESCRIP(I:I).NE.':'.AND.
+     &		  FOLDER_DESCRIP(I:I).NE.'@'.AND.
+     &		  FOLDER_DESCRIP(I:I).NE.'%') THEN
+		 I = I + 1
+	      ELSE
+		 I = FLEN + 2
+	      END IF
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION MAIL_POST()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	IF (NEWS_FEED()) THEN
+	   MAIL_POST = INDEX(FOLDER_DESCRIP,'[').GT.0
+	ELSE
+	   MAIL_POST = INDEX(FOLDER_DESCRIP,'<').GT.0
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin10.for b/decus/vmslt98a/bulletin/bulletin10.for
new file mode 100755
index 0000000000000000000000000000000000000000..308674cf993c1e06b7f75122d4fe54c0bd5aeff2
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin10.for
@@ -0,0 +1,4082 @@
+C
+C  BULLETIN10.FOR, Version 2/27/97
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	INTEGER FUNCTION NEWS_READ()
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	PARAMETER CR = CHAR(13), LF = CHAR(10)
+
+	COMMON /NEWS_INIT/ END_READ
+
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+
+	NEWS_READ = 1
+
+	IF (END_READ.EQ.0) THEN
+	   IER = NEWS_READ_PACKET(BUFFER(:1024))
+	   IF (IER.LE.0) THEN
+	      CALL NEWS_LOGOUT
+	      NEWS_READ = 0
+	      RETURN
+	   END IF
+	   START_READ = 1
+	   END_READ = IER
+	END IF
+
+	IF (END_READ.EQ.0) THEN
+	   NEWS_READ = 0
+	   RETURN
+	END IF
+
+	DO WHILE (NEWS_READ.GT.0)
+	   LAST_LF_SEEN = LF_SEEN
+	   LAST_REAL_LF_SEEN = REAL_LF_SEEN
+	   END_LINE = INDEX(BUFFER(START_READ:END_READ),LF)
+	   CR_SEEN = INDEX(BUFFER(START_READ:END_READ),CR)
+	   IF (CR_SEEN.GT.0) THEN
+	      IF (END_LINE.GT.0) THEN
+		 IF (CR_SEEN.EQ.END_LINE-2.AND.BUFFER(START_READ+CR_SEEN:
+     &		     START_READ+CR_SEEN).EQ.CR) CR_SEEN = CR_SEEN + 1
+	      ELSE
+		 IF (START_READ+CR_SEEN.EQ.END_READ.AND.
+     &		     BUFFER(END_READ:END_READ).EQ.CR) CR_SEEN = 0
+	      END IF
+	   END IF
+	   IF ((END_LINE.EQ.0.AND.CR_SEEN+START_READ-1.LT.END_READ.AND.
+     &			CR_SEEN.GT.0).OR.CR_SEEN.LT.END_LINE-1) THEN
+	      END_LINE = CR_SEEN
+	      CR_SEEN = 1
+	   ELSE
+	      CR_SEEN = 0
+	   END IF
+	   LF_SEEN = END_LINE.GT.0
+	   IF (END_LINE.GT.257-CR_SEEN.OR.
+     &	       (END_LINE.EQ.0.AND.END_READ-START_READ.GE.254)) THEN
+	      END_LINE = 255
+	      IF (.NOT.HEADER_SEEN) END_LINE = 254
+	   END IF
+	   REAL_LF_SEEN = INDEX(BUFFER(START_READ:END_READ),LF).LE.END_LINE
+	   IF (END_LINE.GT.0) THEN
+	      SB = START_READ
+	      END_LINE = END_LINE + SB - 1
+	      EB = END_LINE
+	      IF (BUFFER(EB:EB).EQ.LF) EB = EB - 1
+	      IF (BUFFER(EB:EB).EQ.CR) EB = EB - 1
+	      IF (BUFFER(EB:EB).EQ.CR) EB = EB - 1
+	      IF (END_LINE.LT.END_READ) THEN
+		 START_READ = END_LINE + 1
+	      ELSE
+		 END_READ = 0
+	      END IF
+	      IF (EB.GT.0.OR.LAST_LF_SEEN) RETURN
+	   ELSE
+	      BUFFER = BUFFER(START_READ:END_READ)
+	      END_READ = END_READ - START_READ + 1
+	      IER = NEWS_READ_PACKET(BUFFER(END_READ+1:END_READ+1024))
+	      IF (IER.LE.0) THEN
+		 NEWS_READ = 0
+		 RETURN
+	      ELSE
+		 START_READ = 1
+		 END_READ = END_READ + IER
+	      END IF
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION NEWS_WRITE(WRITE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	PARAMETER CR = CHAR(13), LF = CHAR(10)
+
+	COMMON /NEWS_INIT/ END_READ
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LOCALPOST/ LOCAL_POST
+
+	CHARACTER*(*) WRITE
+
+	LOGICAL TRY_RECONNECT/.FALSE./
+
+	IF (LOCAL_POST) THEN
+	   WRITE (8,'(A)') WRITE(:MIN(LEN(WRITE),256))
+	   DO I=1,LEN(INPUT),255
+	      CALL COMPRESS(WRITE,INPUT,L)
+	      LENGTH = LENGTH + MAX(1,L) + 1
+	   END DO
+	   NEWS_WRITE = .TRUE.
+	   RETURN
+	END IF
+
+	END_READ = 0
+
+	IF (WRITE.EQ.' ') THEN
+	   NEWS_WRITE = NEWS_WRITE_PACKET(CR//LF)
+	ELSE
+	   NEWS_WRITE = NEWS_WRITE_PACKET(WRITE//CR//LF)
+	END IF
+
+	IF (.NOT.NEWS_WRITE.AND..NOT.TRY_RECONNECT) THEN
+	   TRY_RECONNECT = .TRUE.
+	   NEWS_WRITE = NEWS_RECONNECT(WRITE)
+	   TRY_RECONNECT = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	LOGICAL FUNCTION NEWS_RECONNECT(WRITE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*(*) WRITE
+
+	CHARACTER*8 NUMBER
+
+	CHARACTER*(FOLDER_RECORD) FOLDER2_COM
+
+	NEWS_RECONNECT = .FALSE.
+
+	CALL NEWS_LOGOUT
+
+	IF (.NOT.NEWS_LOGIN()) RETURN
+
+	IF (FOLDER(:1).GE.'a'.AND.FOLDER(:1).LE.'z') THEN
+	   FOLDER2_COM = FOLDER1_COM
+	   FOLDER1 = FOLDER
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP
+	   CALL NEWS_GROUP(IER)
+	   IF (IER.NE.0) RETURN
+	   FOLDER1_COM = FOLDER2_COM
+
+	   IF (.NOT.OTS$CVT_L_TI(BULL_POINT+1,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	END IF
+
+	IF (.NOT.NEWS_WRITE(WRITE)) RETURN
+
+	NEWS_RECONNECT = .TRUE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_LOGOUT
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_CONNECTED/ NEWS_CONNECTED
+
+	CALL NEWS_DISCONNECT
+	NEWS_CONNECTED = .FALSE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_DELETE(SBULL,IMMEDIATE,SUBJ,I,FOLDER1_COM,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /HEADER/ HEADER
+
+	CHARACTER*(*) SUBJ,FOLDER1_COM
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE(REMOTE_UNIT,'(4A)',IOSTAT=IER)
+     &			 4,SBULL,IMMEDIATE,SUBJ
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	ELSE IF (REMOTE_SET.GE.3) THEN
+	   IF (TEST_NEWS_OWNER().OR.SETPRV_PRIV()) THEN
+	      IF (REMOTE_SET.EQ.4) THEN
+		 HEADER_SAVE = HEADER
+		 HEADER = .TRUE.
+		 CALL OPEN_BULLFIL_SHARED
+		 ILEN = LINE_LENGTH + 1
+		 DO WHILE (ILEN.GT.0)
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    IF (INPUT(:11).EQ.'Message-ID:') THEN
+		       MESSAGE_ID = INPUT(14:ILEN-1)
+		       ILEN = 0
+		    END IF
+		 END DO
+		 CALL CLOSE_BULLFIL
+		 HEADER = HEADER_SAVE
+	      END IF
+	      CALL NEWS_POST('cancel',0,IER,SUBJ)
+	   ELSE IF (REMOTE_SET.EQ.3) THEN
+	      WRITE (6,'('' ERROR: Not owner of message.'')')
+	   END IF
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_NEWS_OWNER()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	CHARACTER*12 HIGHFROM
+
+	CALL STR$UPCASE(HIGHFROM,FROM)
+	IF (LPATH.EQ.0) CALL GET_PATHNAME
+	TEST_NEWS_OWNER = FROM.EQ.USERNAME.OR.
+     &	    (HIGHFROM.EQ.USERNAME.AND.
+     &	    MESSAGE_ID(FIRST_INDEX(MESSAGE_ID,'@%'):
+     &	    TRIM(MESSAGE_ID)).EQ.
+     &	    PATHNAME(FIRST_INDEX(PATHNAME,'@%'):LPATH))
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION FIRST_INDEX(INPUT,FIND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,FIND
+
+	FIRST_INDEX = 0
+
+	DO I=1,LEN(FIND)
+	   J = INDEX(INPUT,FIND(I:I))
+	   IF (J.GT.0.AND.(FIRST_INDEX.EQ.0.OR.J.LT.FIRST_INDEX))
+     &		FIRST_INDEX = J
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_DIRECTORY_COMMAND(START,END,REVERSE,ALL_DIR,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /XHDR/ XHDR
+	LOGICAL XHDR /.FALSE./
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*8 NUMBER,NUMBER1
+
+	CHARACTER*1024 TEMP
+
+	DATA QXHDR1 /0/
+
+	IF (XHDR) THEN
+	   IF (QXHDR1.NE.0) THEN                ! Is queue empty?
+	      QXHDR = QXHDR1            ! No, set queue pointer to head
+	   ELSE                         ! Else if queue is empty
+	      CALL INIT_QUEUE(QXHDR,TEMP)
+	      QXHDR1 = QXHDR            ! Init header pointer
+	   END IF
+	END IF
+
+	SYSTEM = 0
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   IF (REVERSE) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER) 13,END,START
+	   ELSE
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER) 13,START,END
+	   END IF
+	ELSE
+	   IER = 2
+	   NUMDIR = END - START + 1
+	   IF (START.LT.F_START) THEN
+	      START = F_START
+	      END = START + NUMDIR - 1
+	   END IF
+	END IF
+
+	STAT = .TRUE.
+
+	IF (REMOTE_SET.EQ.3.AND.XHDR) THEN
+	   STAT = .FALSE.
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.OTS$CVT_L_TI(END,NUMBER1,,,)) RETURN
+	   DO WHILE (NUMBER1(1:1).EQ.' ')
+	      NUMBER1 = NUMBER1(2:)
+	   END DO
+	   NUMDIR1 = 0
+	   DO WHILE (NUMDIR1.LT.NUMDIR)
+	      IF (.NOT.NEWS_WRITE('XHDR DATE '//NUMBER//'-'//NUMBER1))
+     &								RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (BUFFER(:2).NE.'22') THEN
+		 IF (NUMDIR1.EQ.0) THEN
+		    IER = 0
+		    END = START - 1
+		    RETURN
+		 ELSE
+		    NUMDIR = NUMDIR1
+		 END IF
+	      ELSE
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IF (NUMDIR1.EQ.0.AND.BUFFER(SB:EB).NE.'.') THEN
+		    IF (.NOT.OTS$CVT_TI_L(BUFFER(SB:INDEX(BUFFER(SB:EB),' ')
+     &			+SB-2),START,,%VAL(1))) RETURN
+		 END IF
+		 DO WHILE (BUFFER(SB:EB).NE.'.')
+		    IF (NUMDIR1.LT.NUMDIR) THEN
+		       NUMDIR1 = NUMDIR1 + 1
+		       TEMP = BUFFER(SB:EB)
+		       CALL WRITE_QUEUE(%VAL(QXHDR),QXHDR,TEMP)
+		    END IF
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+		 IF (NUMDIR1.EQ.0) THEN
+		    IF (START.LE.F_START) THEN
+		       IF (END.GE.F_NBULL) RETURN
+		       START = MIN(F_NBULL,END+1)
+		    ELSE
+		       START = MAX(F_START,START-NUMDIR)
+		    END IF
+		    END = START + NUMDIR - 1
+		    IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+		    IF (.NOT.OTS$CVT_L_TI(END,NUMBER1,,,)) RETURN
+		    DO WHILE (NUMBER1(1:1).EQ.' ')
+		       NUMBER1 = NUMBER1(2:)
+		    END DO
+		 ELSE IF (NUMDIR1.LT.NUMDIR) THEN
+		    STAT = .TRUE.
+		    IF (.NOT.NEWS_WRITE('STAT '//TEMP(:INDEX(TEMP,' ')-1)))
+     &								 RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		    IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		    IF (BUFFER(:2).NE.'22') THEN
+		       NUMDIR = NUMDIR1
+		    ELSE
+		       NUMBER = BUFFER(SB+4:INDEX(BUFFER(SB+4:),' ')+SB+2)
+		       IF (.NOT.OTS$CVT_TI_L(NUMBER,
+     &						MSG_NUM,,%VAL(1))) RETURN
+		       DO WHILE (NUMBER(LEN(NUMBER):).EQ.' ')
+			  NUMBER = ' '//NUMBER(1:)
+		       END DO
+		       MSG_NUM = MSG_NUM + (NUMDIR - NUMDIR1) - 1
+		       IF (.NOT.OTS$CVT_L_TI(MSG_NUM,NUMBER1,,,)) RETURN
+		       DO WHILE (NUMBER1(1:1).EQ.' ')
+			  NUMBER1 = NUMBER1(2:)
+		       END DO
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   CALL OTS$CVT_L_TI(START,NUMBER,,,)
+	   NUMBER1 = TEMP(:INDEX(TEMP,' ')-1)
+	   END = START + NUMDIR - 1
+	   DO I=1,2
+	      IF (I.EQ.1) THEN
+		 IF (.NOT.NEWS_WRITE
+     &		  ('XHDR SUBJECT '//NUMBER//'-'//NUMBER1)) RETURN
+	      ELSE
+		 IF (.NOT.NEWS_WRITE
+     &		  ('XHDR FROM '//NUMBER//'-'//NUMBER1)) RETURN
+	      END IF
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (BUFFER(:2).EQ.'22') THEN
+		 QXHDR = QXHDR1
+		 IF (.NOT.NEWS_READ()) RETURN
+		 NUMDIR1 = 0
+		 DO WHILE (BUFFER(SB:EB).NE.'.'.AND.NUMDIR1.LT.NUMDIR)
+		    NUMDIR1 = NUMDIR1 + 1
+		    CALL READ_QUEUE(%VAL(QXHDR),DUMMY,TEMP)
+		    DO WHILE (BUFFER(SB:EB).NE.'.'.AND.
+     &			.NOT.OTS$CVT_TI_L(BUFFER(SB:INDEX(
+     &			BUFFER(SB:EB),' ')+SB-2),J,,%VAL(1)))
+		       IF (.NOT.NEWS_READ()) RETURN
+		    END DO
+		    SB1 = INDEX(BUFFER(SB:EB),' ')+SB-1
+		    SB1 = FIRST_ALPHA(BUFFER(SB1:EB))+SB1-1
+		    TEMP(I*256+1:) = BUFFER(SB1:EB)
+		    CALL WRITE_QUEUE(%VAL(QXHDR),QXHDR,TEMP)
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+	      END IF
+	   END DO
+	   QXHDR = QXHDR1
+	   IER = 0
+	ELSE IF (REMOTE_SET.EQ.3.AND..NOT.XHDR) THEN
+	   STAT = .TRUE.
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).NE.'22') THEN
+	      IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (.NOT.OTS$CVT_TI_L(BUFFER(SB+4:
+     &		  INDEX(BUFFER(SB+4:),' ')+SB+2),I,,%VAL(1))) RETURN
+	      IF (BUFFER(:2).NE.'22'.OR.I.LT.START) THEN
+		 BUFFER(:3) = '500'
+		 DO WHILE (START.LE.F_NBULL.AND.BUFFER(:2).NE.'22')
+		    START = START + 1
+		    IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+		 IF (BUFFER(:2).NE.'22') THEN
+		    IER = 0
+		    END = START - 1
+		    RETURN
+		 END IF
+	      END IF
+	      IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+	      END = START + NUMDIR - 1
+	   END IF
+	   IER = 0
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   I = START
+	   DO WHILE (IER.EQ.0.AND.I.LE.END)
+	      IF (REMOTE_SET.EQ.1) THEN
+		 READ(REMOTE_UNIT,'(A)',IOSTAT=IER) BULLDIR_ENTRY
+	      ELSE IF (XHDR) THEN
+		 CALL READ_QUEUE(%VAL(QXHDR),QXHDR,TEMP)
+		 LTEMP = INDEX(TEMP,' ')
+		 CALL OTS$CVT_TI_L(TEMP(:LTEMP-1),MSG_NUM,,%VAL(1))
+		 CALL NEWS_TIME(TEMP(LTEMP+1:TRIM(TEMP(:256))),MSG_BTIM)
+		 DO J=257,512
+		    IF (TEMP(J:J).LT.' '.OR.ICHAR(TEMP(J:J)).GT.126)
+     &			TEMP(J:J) = ' '
+		 END DO
+		 DESCRIP = TEMP(257:512)
+		 CALL GET_FROM(FROM,TEMP(512:768),TRIM(TEMP(512:768)))
+	      ELSE
+		 IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			INDEX(BUFFER(SB+4:),' ')+SB+2),MSG_NUM,,%VAL(1))
+		 CALL NEWS_HEADER(IER)
+		 IF (IER.NE.0) RETURN
+	      END IF
+	      CALL WRITE_QUEUE(%VAL(ALL_DIR),ALL_DIR,BULLDIR_ENTRY)
+	      I = I + 1
+	      IF (REMOTE_SET.EQ.3.AND..NOT.XHDR.AND.I.LE.END) THEN
+		 IER = 2
+		 IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IF (BUFFER(:3).NE.'223') THEN
+		    END = I - 1
+		    IER = 0
+		    RETURN
+		 END IF
+		 IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IER = 0
+	      END IF
+	   END DO
+	END IF
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   IER = 1
+	   IF (STAT) THEN
+	      IF (.NOT.OTS$CVT_L_TI(BULL_POINT,NUMBER,,,)) RETURN
+	      IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	   END IF
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_LOGIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_CONNECTED/ NEWS_CONNECTED
+	LOGICAL NEWS_CONNECTED /.FALSE./
+
+	COMMON /XHDR/ XHDR
+	LOGICAL XHDR /.FALSE./
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+
+	IF (.NOT.NEWS_CONNECTED) THEN
+	   NEWS_LOGIN = .FALSE.
+	   CALL START_NEWS_TIMER()
+	   NEWS_CONNECTED = NEWS_CONNECT()
+	   CALL CANCEL_NEWS_TIMER()
+	   IF (.NOT.NEWS_CONNECTED) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (INDEX(BUFFER(SB:EB),'InterNetNews').GT.0) THEN
+	      IF (.NOT.NEWS_WRITE('mode reader')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	   END IF
+	   IF (.NOT.NEWS_WRITE('XHDR')) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   XHDR = BUFFER(:3).NE.'500'
+	   HEADER_SEEN = .FALSE.
+	   LF_SEEN = .FALSE.
+	   LAST_LF_SEEN = .FALSE.
+	   REAL_LF_SEEN = .FALSE.
+	   LAST_REAL_LF_SEEN = .FALSE.
+	END IF
+
+	NEWS_LOGIN = .TRUE.
+
+	RETURN
+	END
+
+
+	SUBROUTINE CONVERT_TO_GMT(BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MONTHS/ MONTH
+	CHARACTER*36 MONTH
+	DATA MONTH/'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'/
+
+	DIMENSION GMT_DIFF(2),BTIM(2)
+
+	CHARACTER HOUR*8
+	DATA HOUR /' '/
+
+	PARAMETER NZONES = 5
+
+	COMMON /ZONE/ ZONE,LZONE
+	CHARACTER*4 ZONE
+
+	CHARACTER ZONES*(NZONES*4)
+	DATA ZONES /'EST CST MST PST IST'/
+
+	CHARACTER*8 TIMES(1)
+	DATA TIMES /'-5:30'/
+
+	CHARACTER TIME*12
+
+	TO_GMT = .TRUE.
+
+	ENTRY CONVERT_FROM_GMT(BTIM)
+
+	IF (HOUR.EQ.' ') THEN
+	   IF (.NOT.SYS_TRNLNM_SYSTEM('LISP$TIME_ZONE',HOUR)) THEN
+	      IF (SYS_TRNLNM_SYSTEM('MULTINET_TIMEZONE',ZONE)
+     &	       .OR.SYS_TRNLNM_SYSTEM('PMDF_TIMEZONE',ZONE)) THEN
+		 IF (INDEX(ZONES,ZONE)/4.LT.4) THEN
+		    HOUR = CHAR(ICHAR('4')+(INDEX(ZONES,ZONE)+3)/4)//':00'
+		 ELSE
+		    HOUR = TIMES((INDEX(ZONES,ZONE)+3)/4-4)
+		 END IF
+	      ELSE
+		 HOUR = '00:00'
+	      END IF
+	   ELSE
+	      HOUR = HOUR(:TRIM(HOUR))//':00'
+	   END IF
+	   ZONE = 'GMT'
+	   IER = OTS$CVT_TI_L(HOUR(:INDEX(HOUR,':')-1),DIFF,,%VAL(1))
+	   IF (DIFF.GE.5.AND.DIFF.LE.8) THEN
+C
+C  Following computes DST based on US formula
+C
+	      IER = SYS$ASCTIM(,TIME,BTIM,)
+	      IER = OTS$CVT_TI_L(TIME(:2),DATE,,%VAL(1))
+	      CALL LIB$DAY_OF_WEEK(BTIM,DAY)
+	      M = (INDEX(MONTH,TIME(4:6))+2)/3
+	      IF (M.GE.4.AND.M.LE.10.AND.(M.NE.4.OR.DAY.LT.DATE)
+     &			.AND.(M.NE.10.OR.DATE-DAY.LT.24)) THEN
+		 DIFF = DIFF - 1
+		 IER = OTS$CVT_L_TI(DIFF,HOUR(:1),,,)
+	      END IF
+	   END IF
+	   IF (DIFF.LT.0) THEN
+	      PAST = .TRUE.
+	      HOUR = HOUR(2:)
+	   ELSE IF (DIFF.GT.12) THEN
+	      PAST = .TRUE.
+	      DIFF = 24 - DIFF
+	      HOUR(3:) = HOUR(INDEX(HOUR,':'):)
+	      IER = OTS$CVT_L_TI(DIFF,HOUR(:2),,,)
+	      IF (HOUR(:1).EQ.' ') HOUR = HOUR(2:)
+	   ELSE
+	      PAST = .FALSE.
+	   END IF
+	   LZONE = TRIM(ZONE)
+	   IER = SYS_BINTIM('0 '//HOUR(:TRIM(HOUR)),GMT_DIFF)
+	END IF
+
+	IF ((PAST.AND..NOT.TO_GMT).OR.(.NOT.PAST.AND.TO_GMT)) THEN
+	   IER = LIB$SUBX(BTIM,GMT_DIFF,BTIM)
+	ELSE
+	   IER = LIB$ADDX(BTIM,GMT_DIFF,BTIM)
+	END IF
+
+	TO_GMT = .FALSE.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE START_NEWS_TIMER()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER TIMADR(2)                       ! Buffer containing time
+						  ! in desired system format.
+	CHARACTER TIMBUF*16,SEC*4
+	DATA TIMBUF/'0 00:00:00.00'/
+
+	EXTERNAL KILL_NEWS_CONNECT
+
+	IF (TIMBUF(9:10).EQ.'00') THEN
+	   CALL LIB$GET_EF(WAITEFN)
+	   TIMBUF(9:10) = '30'
+	   IF (SYS_TRNLNM('BULL_NEWS_TIMER',SEC)) THEN
+	      IER = OTS$CVT_TI_L(SEC(:TRIM(SEC)),I,,%VAL(1))
+	      IF (IER.AND.I.GT.0) THEN
+		 IF (TRIM(SEC).EQ.1) THEN
+		    TIMBUF(9:10) = '0'//SEC(:1)
+		 ELSE
+		    TIMBUF(9:10) = SEC
+		 END IF
+	      END IF
+	   END IF
+	   IER = SYS$BINTIM(TIMBUF(:13),TIMADR)
+	END IF
+
+	IER = SYS$SETIMR(%VAL(WAITEFN),TIMADR,KILL_NEWS_CONNECT,)
+
+	RETURN
+
+	ENTRY CANCEL_NEWS_TIMER()
+
+	IER = SYS$CANCEL(%VAL(WAITEFN))
+
+	RETURN
+	END
+
+
+	SUBROUTINE KILL_NEWS_CONNECT()
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_CONNECTED/ NEWS_CONNECTED
+
+	IF (NEWS_CONNECTED) RETURN
+
+	NLUN = NEWS_GET_CHAN()
+
+	IER = SYS$CANCEL(%VAL(NLUN))
+
+	CALL NEWS_DISCONNECT()
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_HEADER(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /FOLLOWUP/ FOLLOWUP
+	CHARACTER*128 FOLLOWUP
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	COMMON /SENDER/ SENDER_LINE
+	CHARACTER*256 SENDER_LINE
+
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+
+	COMMON /NEWS2BULL/ NEWS2BULL
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	EX_BTIM(1) = 0
+	EX_BTIM(2) = 0
+
+	DESCRIP = ' '
+	FROM = ' '
+	SUBJECT_LINE = ' '
+	FROM_LINE = ' '
+	SENDER_LINE = ' '
+	NEWSGROUPS = ' '
+	FOLLOWUP = ' '
+	LREF = 0
+	NEWS2BULL = .FALSE.
+
+	MSGNUM = BUFFER(5:INDEX(BUFFER(5:),' ')-1+4)
+	LAST_FROM = .FALSE.
+
+	DO WHILE (BUFFER(SB:EB).NE.'.'.OR..NOT.LAST_REAL_LF_SEEN)
+	   IER = NEWS_READ()
+	   IF (.NOT.IER) RETURN
+	   IF (BUFFER(SB:EB).NE.'.') THEN
+	      IF (BUFFER(SB:SB+7).EQ.'Subject:'.AND.EB.GE.SB+9) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+9:EB))+SB+8
+		 DO I=SB1,EB
+		    IF (BUFFER(I:I).LT.' '.OR.ICHAR(BUFFER(I:I)).GT.126)
+     &			BUFFER(I:I) = ' '
+		 END DO
+		 SUBJECT_LINE = 'Subj: '//BUFFER(SB1:EB)
+		 DESCRIP = BUFFER(SB1:EB)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+4).EQ.'Date:'.AND.EB.GE.SB+6) THEN
+		 CALL NEWS_TIME(BUFFER(SB+6:EB),MSG_BTIM)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+7).EQ.'Expires:'.AND.EB.GE.SB+9) THEN
+		 CALL NEWS_TIME(BUFFER(SB+9:EB),EX_BTIM)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+4).EQ.'From:'.AND.EB.GE.SB+6) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+6:EB))+SB+5
+		 FROM_LINE = 'From: '//BUFFER(SB1:EB)
+		 CALL GET_FROM(FROM,BUFFER(SB1:EB),EB-SB1+1)
+		 LAST_FROM = .TRUE.
+	      ELSE IF (BUFFER(SB:SB+6).EQ.'Sender:'.AND.EB.GE.SB+8) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+8:EB))+SB+7
+		 SENDER_LINE = ': '//BUFFER(SB1:EB)
+		 LAST_FROM = .TRUE.
+	      ELSE IF (BUFFER(SB:SB+10).EQ.'Message-ID:'.AND.
+     &						    EB.GT.SB+11) THEN
+		 NEWS_MSGID = BUFFER(SB+13:EB-1)
+		 IF (LREF.EQ.0) THEN
+		    REFERENCES = BUFFER(SB+12:EB)
+		 ELSE
+		    REFERENCES = REFERENCES(:LREF)//' '//
+     &				BUFFER(SB+12:EB)
+		 END IF
+		 LREF = TRIM(REFERENCES)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+10).EQ.'Newsgroups:'.AND.
+     &						    EB.GT.SB+11) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+12:EB))+SB+11
+		 NEWSGROUPS = BUFFER(SB1:EB)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+11).EQ.'Followup-To:'.AND.
+     &						    EB.GT.SB+12) THEN
+		 SB1 = FIRST_ALPHA(BUFFER(SB+13:EB))+SB+12
+		 FOLLOWUP = BUFFER(SB1:EB)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (BUFFER(SB:SB+10).EQ.'References:'.AND.
+     &						    EB.GT.SB+11) THEN
+		 IF (LREF.EQ.0) THEN
+		    REFERENCES = BUFFER(SB+12:EB)
+		 ELSE
+		    REFERENCES = BUFFER(SB+12:EB)//' '//
+     &				REFERENCES(:LREF)
+		 END IF
+		 LREF = TRIM(REFERENCES)
+		 LAST_FROM = .FALSE.
+	      ELSE IF (INDEX(BUFFER(SB:),
+     &		       'NNTP-Posting-Host:').EQ.1) THEN 
+	         IF (LPATH.EQ.0) CALL GET_PATHNAME
+		 CALL LOWERCASE(BUFFER(SB+19:EB))
+	         SAMEHOST = STREQ(PATHNAME(2:LPATH),BUFFER(SB+19:EB))
+	      ELSE IF (INDEX(BUFFER(SB:),
+     &		       'X-Newsreader: News2bull').EQ.1) THEN 
+	         NEWS2BULL = .TRUE.
+	      ELSE IF (LAST_FROM.AND.BUFFER(SB:SB).EQ.' ') THEN
+		 IF (SENDER_LINE(:1).EQ.':') THEN 
+		    SENDER_LINE = SENDER_LINE(:TRIM(SENDER_LINE))//' '//
+     &				BUFFER(SB+FIRST_ALPHA(BUFFER(SB:EB))-1:EB)
+		 ELSE
+		    FROM_LINE = FROM_LINE(:TRIM(FROM_LINE))//' '//
+     &				BUFFER(SB+FIRST_ALPHA(BUFFER(SB:EB))-1:EB)
+		    CALL GET_FROM(FROM,FROM_LINE(7:),TRIM(FROM_LINE))
+		 END IF
+		 LAST_FROM = .TRUE.
+	      ELSE
+		 LAST_FROM = .FALSE.
+	      END IF
+	      IF (.NOT.LAST_FROM.AND.SENDER_LINE(:1).EQ.':') THEN
+		 SENDER_LINE = 'From'//SENDER_LINE
+	      END IF
+	   END IF
+	END DO
+
+	NEWS2BULL = NEWS2BULL.AND.SAMEHOST
+
+	IER = 0
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION FIRST_ALPHA(INPUT)
+
+	CHARACTER*(*) INPUT
+
+	DO I=1,LEN(INPUT)
+	   IF (ICHAR(INPUT(I:I)).LT.32) INPUT(I:I) = ' '
+	END DO
+
+	DO FIRST_ALPHA=1,LEN(INPUT)
+	   IF (ICHAR(INPUT(FIRST_ALPHA:FIRST_ALPHA)).GT.32) RETURN
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE REMOTE_READ_MESSAGE(BULL_SEARCH,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	CHARACTER*8 NUMBER
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 5,BULL_SEARCH
+	ELSE
+	   IER = 2
+	   IF (BULL_SEARCH.LT.F_START) BULL_SEARCH = F_START
+	   IF (.NOT.OTS$CVT_L_TI(BULL_SEARCH,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('ARTICLE '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).NE.'22') RETURN
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_GET_NEWEST_MSG(IN_BTIM,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	DIMENSION IN_BTIM(2)
+
+	CHARACTER TIME*20,FIRST*80
+
+	CHARACTER*8 NUMBER
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(3A)',IOSTAT=IER) 12,IN_BTIM(1),IN_BTIM(2)
+	   IF (IER.EQ.0) THEN
+	      READ (REMOTE_UNIT,'(A)',IOSTAT=IER) START
+	   END IF
+	ELSE IF (READIT.EQ.1) THEN
+	   I = NEWS_FIND_SUBSCRIBE()
+	   START = (LAST_NEWS_READ2(2,I).AND.'1FFF'X) +
+     &			LAST_NEWS_READ(2,I) + 1
+	   IF (START.GT.F_NBULL) THEN
+	      START = -1
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = MIN(8191,F_NBULL-LAST_NEWS_READ(2,I))
+     &			.OR.(LAST_NEWS_READ2(2,I).AND.'E000'X)
+	   END IF
+	ELSE
+	   START = -1
+	   CALL NEWNEWS(IN_BTIM,IER)
+	   IF (IER.NE.0) START = IER
+C
+C   The following code makes use of the NNTP command NEWNEWS, but is
+C   known to be slow and buggy in many servers.
+C
+C          IER = SYS$ASCTIM(,TIME,IN_BTIM,)
+C          CALL DATE_TIME(TIME)
+C          SKIP = 0
+C          DO WHILE (SKIP.GE.0)
+C             IF (.NOT.NEWS_WRITE('NEWNEWS '//FOLDER_NAME(:TRIM(
+C     &           FOLDER_NAME))//' '//TIME)) RETURN
+C             IF (.NOT.NEWS_READ()) RETURN
+C             IF (BUFFER(:2).EQ.'23') THEN
+C                IF (.NOT.NEWS_READ()) CALL EXIT
+C                DO I=1,SKIP
+C                   IF (.NOT.NEWS_READ()) CALL EXIT
+C                END DO
+C                IF (FIRST.EQ.'.') RETURN
+C                DO WHILE (BUFFER(SB:EB).NE.'.')
+C                   IF (.NOT.NEWS_READ()) CALL EXIT
+C                END DO
+C                IF (.NOT.NEWS_WRITE('STAT '//FIRST(:TRIM(FIRST))))
+C     &                                   CALL EXIT
+C                IF (.NOT.NEWS_READ()) CALL EXIT
+C                IF (BUFFER(:2).EQ.'22') THEN
+C                   IF (BUFFER(5:INDEX(BUFFER(5:),' ')+3).EQ.'0') THEN
+C                      I = F_NBULL + 1
+C                      DO WHILE (I.GE.F_START.AND.(FIRST(:TRIM(FIRST)).NE.
+C     &                    BUFFER(INDEX(BUFFER,'<'):INDEX(BUFFER,'>'))
+C     &                    .OR.I.GT.F_NBULL))
+C                         I = I - 1
+C                         IF (.NOT.OTS$CVT_L_TI(I,NUMBER,,,)) RETURN
+C                         IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+C                         IF (.NOT.NEWS_READ()) RETURN
+C                      END DO
+C                      IF (I.GE.F_START) START = I
+C                   ELSE
+C                      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+C     &                   INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+C                   END IF
+C                   RETURN
+C                END IF
+C             END IF
+C             SKIP = SKIP + 1
+C          END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_COPY_BULL(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(A)',IOSTAT=IER1) 2
+	   IER = IER1
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_WRITE_BULL_FILE(OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) OUTPUT
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 6,OUTPUT
+	ELSE
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_REMOTE_MESSAGE(IER)
+C
+C  SUBROUTINE GET_REMOTE_MESSAGE
+C
+C  FUNCTION:
+C       Gets remote message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REMOTE_READ_MESSAGE/ SCRATCH_R1
+	DATA SCRATCH_R1 /0/
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	COMMON /LOCAL_UPDATE/ LOCAL_UPDATE1
+
+	COMMON /HEADER_SEEN/ HEADER_SEEN
+	COMMON /LF/ LF_SEEN,LAST_LF_SEEN,LAST_REAL_LF_SEEN
+
+	CHARACTER*256 TEMP
+
+	IF (SCRATCH_R1.NE.0) THEN               ! Is queue empty?
+	   SCRATCH_R = SCRATCH_R1               ! No, set queue pointer to head
+	ELSE                                    ! Else if queue is empty
+	   CALL INIT_QUEUE(SCRATCH_R,INPUT)
+	   SCRATCH_R1 = SCRATCH_R               ! Init header pointer
+	END IF
+
+	ILEN = 128
+	IER = 0
+	LENGTH = 0
+	LTEMP = 0
+	HEADER_SEEN = .FALSE.
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   LSUB = TRIM(SUBJECT_LINE)
+	   LFRO = TRIM(FROM_LINE)
+	   IF (LOCAL_UPDATE1.NE.0) THEN
+	      ILEN = 1
+	      INPUT(:1) = CHAR(0)
+	   END IF
+	END IF
+
+	DO WHILE (ILEN.GT.0.AND.IER.EQ.0)
+	   IF (REMOTE_SET.EQ.1) THEN
+	      READ (REMOTE_UNIT,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	   ELSE
+	      IF (ILEN.EQ.128) ILEN = 0
+	      IF (LTEMP.GT.0) THEN
+		 ILEN = MIN(128,LTEMP)
+		 INPUT = TEMP(:ILEN)
+		 LTEMP = LTEMP - ILEN
+	      END IF
+	      IF (ILEN.LT.128) THEN
+		 IF (LFRO.GT.0) THEN
+		    IF (LOCAL_UPDATE1.NE.0) THEN
+		       CALL COMPRESS(FROM_LINE(:LFRO),FROM_LINE,LFRO)
+		    END IF
+		    LTEMP = LFRO
+		    LFRO = 0
+		    IER = 0
+		    TEMP = CHAR(LTEMP)//FROM_LINE
+		    LTEMP = LTEMP + 1
+		    LINP = MIN(LTEMP,128-ILEN)
+		    INPUT = INPUT(:ILEN)//TEMP(:LINP)
+		    ILEN = ILEN + LINP
+		    LTEMP = LTEMP - LINP
+		    TEMP = TEMP(LINP+1:)
+		 ELSE IF (LSUB.GT.0) THEN
+		    IF (LOCAL_UPDATE1.NE.0) THEN
+		       CALL COMPRESS(SUBJECT_LINE(:LSUB),SUBJECT_LINE,LSUB)
+		    END IF
+		    LTEMP = LSUB
+		    LSUB = 0
+		    IER = 0
+		    TEMP = CHAR(LTEMP)//SUBJECT_LINE
+		    LTEMP = LTEMP + 1
+		    LINP = MIN(LTEMP,128-ILEN)
+		    INPUT = INPUT(:ILEN)//TEMP(:LINP)
+		    ILEN = ILEN + LINP
+		    LTEMP = LTEMP - LINP
+		    TEMP = TEMP(LINP+1:)
+		 ELSE
+		    IER = NEWS_READ()
+		    IF (IER.AND.(BUFFER(SB:EB).NE.'.'
+     &			.OR..NOT.LAST_REAL_LF_SEEN)) THEN
+		       IER = 0
+		       LTEMP = EB-SB+1
+		       IF (LTEMP.GT.0) THEN
+			  TEMP = CHAR(LTEMP)//BUFFER(SB:SB+LTEMP-1)
+			  IF (.NOT.HEADER_SEEN) THEN
+			     IF (TRIM(TEMP).EQ.0) THEN
+				HEADER_SEEN = .TRUE.
+			     ELSE IF ((INDEX(TEMP,': ').EQ.0.AND.
+     &				   INDEX(TEMP,':'//CHAR(9)).EQ.0.AND.ICHAR(
+     &				   TEMP(2:2)).GT.32.AND.LTEMP.LT.255).OR.
+     &				   (LTEMP.EQ.254.AND..NOT.LAST_LF_SEEN)) THEN
+				TEMP = CHAR(LTEMP+1)
+     &					   //' '//BUFFER(SB:SB+LTEMP-1)
+				LTEMP = LTEMP + 1
+			     END IF
+			  ELSE IF (BUFFER(SB:SB).EQ.'.') THEN
+			     TEMP = CHAR(LTEMP-1)//BUFFER(SB+1:SB+LTEMP-1)
+			     LTEMP = LTEMP - 1
+			  END IF
+			  IF (LOCAL_UPDATE1.NE.0) THEN
+			     CALL COMPRESS(TEMP(2:LTEMP+1),TEMP(2:),LTEMP)
+			     TEMP(:1) = CHAR(LTEMP)
+			  END IF
+		       ELSE
+			  HEADER_SEEN = .TRUE.
+			  TEMP = CHAR(1)//' '
+			  LTEMP = 1
+		       END IF
+		       LTEMP = LTEMP + 1
+		       LINP = MIN(LTEMP,128-ILEN)
+		       INPUT = INPUT(:ILEN)//TEMP(:LINP)
+		       ILEN = ILEN + LINP
+		       LTEMP = LTEMP - LINP
+		       TEMP = TEMP(LINP+1:)
+		    ELSE IF (IER) THEN
+		       IER = 0
+		       INPUT = INPUT(:ILEN)//CHAR(0)
+		       ILEN = -128
+		    ELSE
+		       ILEN = 128
+		    END IF
+		 END IF
+	      ELSE
+		 TEMP = TEMP(129:)
+	      END IF
+	   END IF
+	   IF (IER.NE.0.AND.ILEN.GT.0) THEN
+	      CALL ERRSNS(IDUMMY,IER1)
+	      IF (IER1.EQ.RMS$_RER) THEN        ! Ignore this error
+		 IER = 0
+		 ILEN = 0
+	      ELSE
+		 CALL SYS_GETMSG(IER1)
+		 LENGTH = 0
+		 IER1 = IER
+		 CALL DISCONNECT_REMOTE
+		 IER = IER1     ! IER is set to 0 by DISCONNECT_REMOTE
+	      END IF
+	   ELSE IF (ABS(ILEN).EQ.128) THEN
+	      CALL WRITE_QUEUE(%VAL(SCRATCH_R),SCRATCH_R,INPUT)
+	      LENGTH = LENGTH + 1
+	   END IF
+	END DO
+
+	HEADER_SEEN = .TRUE.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE REMOTE_REMOVE_FOLDER(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+C
+C  SUBROUTINE CONNECT_REMOTE_FOLDER
+C
+C  FUNCTION: Connects to folder that is located on other DECNET node.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	DATA REMOTE_UNIT /15/
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /READIT/ READIT
+
+	COMMON /NEWS_INIT/ END_READ
+
+	COMMON /ALT_FOUND/ ALT_FOUND
+	CHARACTER*128 ALT_FOUND
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*12 FOLDER_BBOARD_SAVE,FOLDER_OWNER_SAVE
+	CHARACTER*44 FOLDER_SAVE
+	CHARACTER*64 ALT_SAVE
+
+	DIMENSION DUMMY(4)
+
+	IF (FOLDER1(:1).GE.'a'.AND.FOLDER1(:1).LE.'z') THEN
+	   ALT_SET_SAVE = ALT_SET()
+	   IF (ALT_SET_SAVE) CALL UNSET_ALT
+	   END_READ = 0
+	   IER = 0
+	   IF (.NOT.NEWS_LOGIN()) THEN
+	      IER = 2
+	      IF (.NOT.TEST_ALT(FOLDER1)) RETURN
+	      IER = 1
+	   END IF
+	   IF (IER.NE.1) CALL NEWS_GROUP(IER)
+	   IF (IER.EQ.1) THEN
+	      IF (TEST_ALT(FOLDER1)) THEN
+		 IER1 = SET_ALT(ALT_FOUND)
+		 IF (IER1) CALL NEWS_GROUP(IER)
+		 IF (.NOT.IER1.OR.IER.NE.0) THEN
+		    CALL UNSET_ALT
+	   	    IF (ALT_SET_SAVE) IER = SET_ALT(ALT_SAVE)
+		    RETURN
+		 END IF
+		 ALT_SAVE = FOLDER1(INDEX(':',FOLDER1)+1:)
+	         IER = 0
+	      ELSE IF (ALT_SET_SAVE) THEN
+	         IER = SET_ALT(ALT_SAVE)
+	      END IF
+	      RETURN
+	   END IF
+	   IF (REMOTE_SET.EQ.1) CLOSE(UNIT=REMOTE_UNIT)
+	   RETURN
+	END IF
+
+	REMOTE_UNIT = 31 - REMOTE_UNIT
+
+	SAME = .TRUE.
+	LEN_BBOARD = TRIM(FOLDER1_BBOARD)
+	IF (INDEX(FOLDER1_BBOARD,'*').GT.0) THEN  ! Remote folder name different
+	   SAME = .FALSE.                         ! from local?  Yes.
+	   LEN_BBOARD = LEN_BBOARD - 1
+	END IF
+
+	OPEN (UNIT=REMOTE_UNIT,STATUS='UNKNOWN',IOSTAT=IER,RECL=256,
+     &		FILE=FOLDER1_BBOARD(3:LEN_BBOARD)//'::"TASK=BULLETIN1"')
+
+	IF (IER.EQ.0) THEN
+	   IF (.NOT.SAME) THEN
+	      FOLDER1_FILE = FOLDER_FILE
+	      FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//FOLDER1
+	      REMOTE_SET_SAVE = REMOTE_SET
+	      REMOTE_SET = .FALSE.
+	      CALL OPEN_BULLDIR
+	      CALL READDIR(0,IER)
+	      CALL CLOSE_BULLDIR
+	      REMOTE_SET = REMOTE_SET_SAVE
+	      FOLDER_FILE = FOLDER1_FILE
+	      FOLDER_SAVE = FOLDER1
+	      FOLDER1 = BULLDIR_HEADER(13:)
+	      IF (NEMPTY.EQ.0) FOLDER1 = FOLDER1(:25)
+	   END IF
+	   SYSLOG = .FALSE.
+	   IF (READIT.EQ.1) THEN
+	      WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 1,'SYSTEM?'
+	      READ(REMOTE_UNIT,'(A)',IOSTAT=IER) IER1
+	      IF (IER1) THEN
+		 WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 1,FOLDER1//'+'
+		 SYSLOG = .TRUE.
+	      END IF
+	   END IF
+	   IF (.NOT.SYSLOG) THEN
+	      WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 1,FOLDER1
+	   END IF
+	   FOLDER_OWNER_SAVE = FOLDER1_OWNER
+	   FOLDER_BBOARD_SAVE = FOLDER1_BBOARD
+	   FOLDER_NUMBER_SAVE = FOLDER1_NUMBER
+	   IF (IER.EQ.0) THEN
+	      IF (SYSLOG) THEN
+		 READ(REMOTE_UNIT,'(7A)',IOSTAT=IER)IER1,READ_ONLY,
+     &		   DUMMY(1),DUMMY(2),DUMMY(3),DUMMY(4),FOLDER1_COM
+	      ELSE
+		 READ(REMOTE_UNIT,'(5A)',IOSTAT=IER)IER1,READ_ONLY,
+     &		   DUMMY(1),DUMMY(2),FOLDER1_COM
+	      END IF
+	   END IF
+	   IF (.NOT.SAME) FOLDER1 = FOLDER_SAVE
+	   FOLDER1_BBOARD = FOLDER_BBOARD_SAVE
+	   FOLDER1_NUMBER =  FOLDER_NUMBER_SAVE
+	   FOLDER1_OWNER = FOLDER_OWNER_SAVE
+	END IF
+
+	IF (IER.NE.0.OR..NOT.IER1) THEN
+	   CLOSE (UNIT=REMOTE_UNIT)
+	   REMOTE_UNIT = 31 - REMOTE_UNIT
+	   IF (IER.EQ.0.AND.FOLDER_NUMBER_SAVE.GE.0.AND.
+     &	       TEST_BULLCP().NE.2) THEN                 ! Not BULLCP process
+	      IF (TEST2(BRIEF_FLAG,FOLDER_NUMBER_SAVE)
+     &		  .OR.TEST2(SET_FLAG,FOLDER_NUMBER_SAVE)) THEN
+		 CALL OPEN_BULLUSER_SHARED
+		 CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+		 CALL CLR2(BRIEF_FLAG,FOLDER_NUMBER_SAVE)
+		 CALL CLR2(SET_FLAG,FOLDER_NUMBER_SAVE)
+		 IF (IER.EQ.0) REWRITE (4) USER_ENTRY
+		 CALL CLOSE_BULLUSER
+	      END IF
+	   END IF
+	   IER = 2
+	ELSE
+	   CLOSE (UNIT=31-REMOTE_UNIT)
+C
+C  If remote folder has returned a last read time for the folder,
+C  and if in /LOGIN mode, or last selected folder was a different
+C  folder, or folder specified with "::", then update last read time.
+C
+	   IF (((FOLDER_NUMBER.NE.FOLDER1_NUMBER.OR.READIT.EQ.1)
+     &		.AND.(DUMMY(1).NE.0.OR.DUMMY(2).NE.0))
+     &		.OR.FOLDER1_NUMBER.EQ.-1) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER1_NUMBER+1),DUMMY)
+	      IF (SYSLOG) THEN
+		 CALL COPY2(LAST_SYS_BTIM(1,FOLDER1_NUMBER+1),DUMMY(3))
+	      END IF
+	   END IF
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE REMOTE_GET_HEADER(BULLETIN_NUM,ICOUNT,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /NEXT/ NEXT
+	LOGICAL NEXT /.FALSE./
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	CHARACTER*8 NUMBER
+
+	DIMENSION IN_BTIM(2)
+
+	IF (REMOTE_SET.EQ.1) THEN
+	   IF (ICOUNT.GE.0) THEN
+	      WRITE (REMOTE_UNIT,'(2A)',IOSTAT=IER) 8,ICOUNT
+	   ELSE
+	      WRITE (REMOTE_UNIT,'(3A)',IOSTAT=IER) 8,-1,MSG_KEY
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (ICOUNT.EQ.0) THEN
+		 READ (REMOTE_UNIT,'(2A)',IOSTAT=IER) ICOUNT,BULLDIR_HEADER
+	      ELSE IF (ICOUNT.EQ.-1) THEN
+		 READ (REMOTE_UNIT,'(2A)',IOSTAT=IER1) IER,BULLDIR_ENTRY
+		 IF (IER1.GT.0) THEN
+		    CALL ERROR_AND_EXIT
+		 ELSE IF (IER.NE.0) THEN
+		    CALL CONVERT_ENTRY_FROMBIN
+		 END IF
+		 RETURN
+	      ELSE
+		 READ (REMOTE_UNIT,'(2A)',IOSTAT=IER) ICOUNT,BULLDIR_ENTRY
+	      END IF
+	   END IF
+	   IF (IER.GT.0) THEN
+	      CALL ERROR_AND_EXIT
+	   ELSE IF (ICOUNT.EQ.1) THEN
+	      CALL CONVERT_HEADER_FROMBIN
+	   ELSE
+	      CALL CONVERT_ENTRY_FROMBIN
+	   END IF
+	ELSE IF (REMOTE_SET.EQ.3) THEN
+	   IF (ICOUNT.EQ.0) THEN
+	      NBULL = F_NBULL
+	      ICOUNT = 1
+	      RETURN
+	   ELSE IF (ICOUNT.EQ.-1) THEN
+	      IER = 2
+	      CALL GET_MSGBTIM(MSG_KEY,IN_BTIM)
+	      CALL REMOTE_GET_NEWEST_MSG(IN_BTIM,START)
+	      IF (START.EQ.-1) RETURN
+	      IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+	      IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+	   ELSE
+	      IER = 2
+	      IF (NEXT.AND..NOT.NEWGROUP) THEN
+		 IF (.NOT.NEWS_WRITE('NEXT')) CALL ERROR_AND_EXIT
+		 IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		 IF (BUFFER(:3).NE.'223') RETURN
+		 IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+		 IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+	      ELSE
+		 IF (ICOUNT.LT.F_START) ICOUNT = F_START
+		 IF (ICOUNT.GT.F_NBULL) ICOUNT = F_NBULL
+		 IF (.NOT.OTS$CVT_L_TI(ICOUNT,NUMBER,,,)) RETURN
+		 IF (.NOT.NEWS_WRITE('HEAD '//NUMBER))
+     &						CALL ERROR_AND_EXIT
+		 IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+	      END IF
+	      IF (BUFFER(:2).NE.'22') THEN
+		 DO WHILE (NEXT.AND.NEWGROUP.AND.ICOUNT.GT.F_START)
+		    ICOUNT = ICOUNT - 1
+		    IF (.NOT.OTS$CVT_L_TI(ICOUNT,NUMBER,,,)) RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD '//NUMBER))
+     &						CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		    IF (BUFFER(:2).EQ.'22') THEN
+		       NEXT = .FALSE.
+		       DO WHILE (BUFFER(SB:EB).NE.'.')
+			  IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		       END DO
+		    END IF
+		 END DO
+		 IF (INCMD(:4).EQ.'BACK'.AND.ICOUNT.GE.F_START) THEN
+		    IF (.NOT.NEWS_WRITE('LAST')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		    IF (BUFFER(:3).NE.'223') RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		 ELSE IF (INCMD(:4).NE.'READ'.AND..NOT.NEXT) THEN
+		    IF (.NOT.NEWS_WRITE('NEXT')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		    IF (BUFFER(:3).NE.'223') RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD')) CALL ERROR_AND_EXIT
+		    IF (.NOT.NEWS_READ()) CALL ERROR_AND_EXIT
+		 END IF
+	      END IF
+	      IF (BUFFER(:2).NE.'22') RETURN
+	      IER = OTS$CVT_TI_L(BUFFER(5:INDEX(BUFFER(5:),' ')+3),
+     &							ICOUNT,,%VAL(1))
+	      IF (.NOT.IER) RETURN
+	      START = ICOUNT
+	      BULLETIN_NUM = START
+	   END IF
+	   NEWGROUP = .FALSE.
+	   MESSAGE_ID = BUFFER(INDEX(BUFFER,'<')+1:INDEX(BUFFER,'>')-1)
+	   IER = 0
+	   CALL NEWS_HEADER(IER)
+	   CALL CONVERT_FROM_GMT(MSG_BTIM)
+	   IF (IER.GT.0) THEN
+	      CALL ERROR_AND_EXIT
+	   ELSE
+	      CALL CONVERT_ENTRY_FROMBIN
+	   END IF
+	   BLOCK = START
+	   MSG_NUM = START
+	   SYSTEM = 0
+	   IF (ICOUNT.NE.-1) THEN
+	      ICOUNT = ICOUNT + 1
+	   ELSE
+	      IER = START
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_MSGBTIM(MSG_KEY,BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER BTIM(2)
+
+	CHARACTER*8 MSG_KEY,INPUT
+
+	INPUT = MSG_KEY
+
+	DO I=1,8
+	   INPUT(9-I:9-I) = MSG_KEY(I:I)
+	END DO
+
+	CALL LIB$MOVC3(8,%REF(INPUT),BTIM(1))
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_GROUP(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	IF (INDEX(FOLDER1_DESCRIP,' ').EQ.0) THEN
+	   IER = 1
+	   RETURN
+	END IF
+
+	IER = NEWS_WRITE('GROUP '//
+     &			 FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,' ')-1))
+	IF (.NOT.IER) RETURN
+
+	IER = NEWS_READ()
+	IF (.NOT.IER) RETURN
+
+	IER = 1
+
+	IF (BUFFER(:3).EQ.'411') RETURN
+
+	NEWGROUP = .TRUE.
+
+	BUFFER = BUFFER(5:)
+
+	IER = OTS$CVT_TI_L(BUFFER(:INDEX(BUFFER,' ')-1),F1_COUNT,,%VAL(1))
+	IF (.NOT.IER) RETURN
+	BUFFER = BUFFER(INDEX(BUFFER,' ')+1:)
+	IER = OTS$CVT_TI_L(BUFFER(:INDEX(BUFFER,' ')-1),F1_START,,%VAL(1))
+	IF (.NOT.IER) RETURN
+	BUFFER = BUFFER(INDEX(BUFFER,' ')+1:)
+	IER = OTS$CVT_TI_L(BUFFER(:INDEX(BUFFER,' ')-1),F1_NBULL,,%VAL(1))
+	IF (.NOT.IER) RETURN
+	BUFFER = BUFFER(INDEX(BUFFER,' ')+1:)
+
+	IER = NEWS_WRITE('STAT')
+	IF (.NOT.IER) RETURN
+
+	IER = NEWS_READ()
+	IF (.NOT.IER) RETURN
+
+	IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			   INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+	IF (IER.AND.START.GT.F1_START) F1_START = START
+
+	IF (F1_START.EQ.0) F1_NBULL = 0
+
+	IER = 0
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_TIME(INTIME,BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INTIME
+
+	CHARACTER*28 TIME
+
+	DIMENSION DIFF(2)
+
+	I = 1
+	LTIME = TRIM(INTIME)
+	DO WHILE (I.LE.LTIME.AND.(ICHAR(INTIME(I:I)).LT.ICHAR('0').OR.
+     &			   ICHAR(INTIME(I:I)).GT.ICHAR('9')))
+	   I = I + 1
+	END DO
+
+	IF (I.GT.LTIME) THEN
+	   CALL SYS_BINTIM('-',BTIM)
+	   RETURN
+	END IF
+
+	CALL STR$UPCASE(TIME,INTIME(I:))
+
+	DO J = 1,2
+	   I = 1
+	   DO WHILE (TIME(I:I).NE.' '.AND.I.LT.LEN(TIME))
+	      I = I + 1
+	   END DO
+	   TIME(I:I) = '-'
+	END DO
+
+	IF (I.EQ.LEN(TIME)) RETURN
+
+	IF (TIME(I+3:I+3).EQ.' ') THEN
+	   IF (TIME(I+1:I+1).EQ.'9'.OR.TIME(I+1:I+1).EQ.'8') THEN
+	      TIME = TIME(:I)//'19'//TIME(I+1:)
+	   ELSE
+	      TIME = TIME(:I)//'20'//TIME(I+1:)
+	   END IF
+	END IF
+
+	I = 1
+	DO J = 1,2
+	   DO WHILE (TIME(I:I).NE.' '.AND.I.LE.LEN(TIME))
+	      I = I + 1
+	   END DO
+	   I = I + 1
+	END DO
+
+	IF (I-2.GT.LEN(TIME).OR.I-2.LE.0) THEN
+	   CALL SYS_BINTIM('-',BTIM)
+	   RETURN
+	END IF
+
+	IF (INDEX(TIME(:I-2),'.').GT.0) THEN
+	   CALL SYS_BINTIM(TIME(:INDEX(TIME(:I-2),'.'))//'00',BTIM)
+	ELSE IF (TIME(I-4:I-4).EQ.':'.AND.TIME(I-7:I-7).EQ.':') THEN
+	   CALL SYS_BINTIM(TIME(:I-2)//'.00',BTIM)
+	ELSE
+	   CALL SYS_BINTIM(TIME(:I-2)//':00.00',BTIM)
+	END IF
+
+	IF (TIME(I:I).EQ.'+'.OR.TIME(I:I).EQ.'-') THEN
+	   IER = SYS_BINTIM('0 '//TIME(I+1:I+2)//':'//TIME(I+3:I+4),DIFF)
+	   IF (IER) THEN
+	      IF (TIME(I:I).EQ.'-') THEN
+		 IER = LIB$SUBX(BTIM,DIFF,BTIM)
+	      ELSE
+		 IER = LIB$ADDX(BTIM,DIFF,BTIM)
+	      END IF
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_LIST
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /LOCAL_UPDATE/ LOCAL_UPDATE1
+	DATA LOCAL_UPDATE1/0/
+
+	COMMON /NEWSLIST/ NEWSLIST
+
+	CHARACTER TODAY*24
+
+	DIMENSION EXPIRED(2)
+
+	CALL LIB$DATE_TIME(TODAY)
+
+	IF (.NOT.NEWS_LOGIN()) RETURN
+
+	IF (.NOT.NEWS_WRITE('LIST')) RETURN
+	IF (.NOT.NEWS_READ()) RETURN
+	IF (BUFFER(:3).NE.'215') RETURN
+
+	SPECIAL = SYS_TRNLNM('BULL_SPECIAL_NEWS_UPDATE','DEFINED').OR.
+     &	 (INDEX(TODAY,' 03:').NE.0)     ! Delete non-existant groups at 3
+
+	CALL INIT_QUEUE(LOCAL_UPDATE1,%DESCR(NEWS_FOLDER_NUMBER))
+
+	LOCAL_UPDATE = LOCAL_UPDATE1
+
+	NEWSLIST = .TRUE.
+	CALL OPEN_BULLNEWS_SHARED       ! Open folder file
+
+	NEWS_FOLDER1_BBOARD = '::'
+
+	CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER1)
+	IF (IER1.NE.0) THEN
+	   NEWS_FOLDER1 = 'a'
+	   NEWS_FOLDER1_NUMBER = 1000
+	   NEWS_F1_COUNT = 1001
+	   NEWS_F1_EXPIRE = 14
+	   NEWS_F1_EXPIRE_LIMIT = 0
+	   NEWS_F1_FLAG = 0
+	   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',EXPIRED)
+	   CALL GET_MSGKEY(EXPIRED,NEWS_F1_EXPIRED_DATE)
+	   WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	END IF
+	NEWS_FLAG_DEFAULT = NEWS_F1_FLAG
+	NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+	NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	IF (NEWS_F1_COUNT.LT.1001) NEWS_F1_COUNT = 1001
+	NEWS_F_COUNT = NEWS_F1_COUNT
+	DAMAGED = .FALSE.
+	DO WHILE (NEWS_READ().AND.BUFFER(SB:EB).NE.'.')
+	   FLEN = INDEX(BUFFER(SB:),' ') - 1
+	   IF (INDEX(BUFFER(SB:),' ').EQ.0) DAMAGED = .TRUE.
+	   NEWS_FOLDER1 = BUFFER(SB:MIN(44,FLEN)+SB-1)
+	   IF (IER1.EQ.0) THEN
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(NEWS_FOLDER1,IER)
+	   END IF
+	   SP = FLEN+SB+1
+	   EP = INDEX(BUFFER(SP:),' ')+SP-2
+	   IF (INDEX(BUFFER(SP:),' ').EQ.0) DAMAGED = .TRUE.
+	   IER2 = OTS$CVT_TI_L(BUFFER(SP:EP),NEWS_F1_NBULL,,%VAL(1))
+	   SP = EP + 2
+	   EP = INDEX(BUFFER(SP:),' ')+SP-2
+	   IF (INDEX(BUFFER(SP:),' ').EQ.0) DAMAGED = .TRUE.
+	   IER2 = OTS$CVT_TI_L(BUFFER(SP:EP),NEWS_F1_START,,%VAL(1))
+	   IF (NEWS_F1_START.EQ.0) NEWS_F1_NBULL = 0
+	   CALL SYS_BINTIM('-',NEWS_F1_NEWEST_BTIM)
+	   SP = EP + 1
+	   IF (IER.EQ.0.AND.IER1.EQ.0)
+     &	      NEWS_F1_FLAG = IBCLR(NEWS_F1_FLAG,10)  ! Old bug caused this.
+	   IF (IER.NE.0.OR.IER1.NE.0) THEN
+	      IF ((FLEN.LE.44.OR.FLEN-44+EB-SP+1.LT.
+     &	          LEN(NEWS_FOLDER1_DESCRIP)).AND.DAMAGED) THEN
+	         IF (FLEN.GT.44) THEN
+		    NEWS_FOLDER1_DESCRIP = BUFFER(SB+44:FLEN+SB-1)//
+     &					   BUFFER(SP:EB)
+	         ELSE
+		    NEWS_FOLDER1_DESCRIP = BUFFER(SP:EB)
+	         END IF
+		 CALL ADD_NEW_NEWS_ENTRY(FLEN,LOCAL_UPDATE)
+	      END IF
+           ELSE
+	      CALL UPDATE_NEWS_ENTRY(SPECIAL,LOCAL_UPDATE,FLEN,SP)
+	   END IF
+	   IF (DAMAGED) THEN
+	      IER = NEWS_READ()
+	      DAMAGED = .FALSE.
+	   END IF
+	END DO
+
+	CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER1)
+	NEWS_F1_COUNT = NEWS_F_COUNT
+	REWRITE (7) NEWS_FOLDER1_COM
+
+	OPEN (UNIT=33,FILE=FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &        'BULL_ALT_NEWS.LIS',IOSTAT=IER,STATUS='OLD',READONLY)
+	
+	DO WHILE (IER.EQ.0)
+	   READ (33,'(A)',IOSTAT=IER) INPUT
+	   IF (IER.EQ.0) THEN 
+	      FLEN = INDEX(INPUT,':')-1
+	      NEWS_FOLDER1 = INPUT(:FLEN)
+	      IF (SET_ALT(INPUT(FLEN+2:))) THEN
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP(NEWS_FOLDER1,IER1)
+		 IF (IER1.NE.0) THEN
+		    FOLDER1_DESCRIP = NEWS_FOLDER1
+	            IF (FLEN.GT.44) THEN
+	   	       NEWS_FOLDER1_DESCRIP = INPUT(45:FLEN)
+	            ELSE
+	               NEWS_FOLDER1_DESCRIP = ' '
+	   	    END IF
+	         END IF
+		 CALL NEWS_GROUP(IER)
+		 IF (IER.EQ.0) THEN 
+	            NEWS_F1_NBULL = F1_NBULL
+	            NEWS_F1_START = F1_START
+		    IF (NEWS_F1_START.EQ.0) NEWS_F1_NBULL = 0
+		    IF (IER1.NE.0) THEN
+		       CALL ADD_NEW_NEWS_ENTRY(FLEN,LOCAL_UPDATE)
+		    ELSE
+	               CALL UPDATE_NEWS_ENTRY(.FALSE.,LOCAL_UPDATE,FLEN,0)
+		    END IF
+		 END IF
+	      END IF
+	   END IF
+	   IF (IER.NE.0) CLOSE (UNIT=33)
+	   IF (ALT_SET()) THEN
+	      CALL UNSET_ALT
+	      IF (.NOT.NEWS_LOGIN()) RETURN
+	   END IF
+	END DO
+
+	IF (SPECIAL) THEN
+	   CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+	   LAST = FOLDER1_NUMBER
+	   DO WHILE (IER.EQ.0)
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+	      DO WHILE (IER.EQ.0.AND.LAST.EQ.FOLDER1_NUMBER) ! oops
+		 DELETE (7)
+		 CALL READ_FOLDER_FILE_TEMP(IER)
+	      END DO
+	      LAST = FOLDER1_NUMBER
+	      IF (IER.EQ.0.AND..NOT.BTEST(NEWS_F1_FLAG,10)) THEN
+		 NEWS_F1_NBULL = F1_NBULL
+		 NEWS_F1_START = F1_START
+		 NEWS_F1_COUNT = F1_COUNT
+		 CALL NEWS_GROUP(IER)
+		 IF (IER.EQ.1.AND.TEST_ALT(NEWS_FOLDER1//
+     &		     NEWS_FOLDER1_DESCRIP)) THEN
+		   IER = 0
+		 ELSE IF (IER.EQ.0.AND..NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+		    IF (BTEST(NEWS_F1_FLAG,8)) THEN
+		       IF (NEWS_F1_LAST.NE.F1_NBULL.AND.
+     &			   F1_START.LE.F1_NBULL) THEN
+			  IF (NEWS_F1_FIRST.GT.F1_START.AND.
+     &			      NEWS_F1_FIRST.GT.F1_NBULL) THEN
+			     NEWS_F1_LAST = 0
+			     REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+			  END IF
+			  IF (NEWS_F1_LAST.LT.F1_NBULL) THEN
+			     CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),
+     &			      LOCAL_UPDATE,%DESCR(NEWS_FOLDER1_NUMBER))
+			  END IF
+		       END IF
+		    ELSE IF (((F1_START.NE.NEWS_F1_START.OR.
+     &			F1_NBULL.NE.NEWS_F1_NBULL).AND.F1_START.GT.0).OR.
+     &			NEWS_F1_COUNT.NE.F1_COUNT) THEN
+		       CALL SYS_BINTIM('-',F1_NEWEST_BTIM)
+		       CALL REWRITE_FOLDER_FILE_TEMP(IER1)
+		    END IF
+		 ELSE IF (IER.EQ.1.AND..NOT.BTEST(NEWS_F1_FLAG,8)) THEN
+		    DELETE (UNIT=7)
+		    IER = 0
+		 ELSE IF (IER.EQ.1) THEN
+		    IF (NEWS_F1_NBULL.LT.NEWS_F1_START
+     &			  .OR.NEWS_F1_START.EQ.0) THEN
+		       CALL CLOSE_BULLNEWS
+		       FOLDER_NUMBER = FOLDER1_NUMBER
+		       CALL SELECT_FOLDER(.FALSE.,IER1)
+		       IF (IER1) THEN
+			  CALL OPEN_BULLDIR_SHARED
+			  CALL READDIR(NEWS_F1_START,IER1)
+			  CALL CLOSE_BULLDIR
+			  IER1 = NEWS_F1_START+1.EQ.IER1
+		       END IF
+		       CALL OPEN_BULLNEWS_SHARED
+		       CALL READ_FOLDER_FILE_KEYNUM_TEMP(FOLDER_NUMBER,IER)
+		       IF (.NOT.IER1) DELETE (UNIT=7)
+		    END IF
+		    IER = 0
+		 END IF
+	      END IF
+	   END DO
+	END IF
+
+	CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,%DESCR(0))
+
+	CALL CLOSE_BULLNEWS
+	NEWSLIST = .FALSE.
+
+	IF (SYS_TRNLNM('BULL_NEWS_RECOUNT','DEFINED')) CALL RECOUNT
+
+	RETURN
+	END
+
+
+	SUBROUTINE LOWERCASE(INPUT)
+
+	CHARACTER*(*) INPUT
+
+	DO I=1,LEN(INPUT)
+	   IF (INPUT(I:I).GE.'A'.AND.INPUT(I:I).LE.'Z') THEN
+	      INPUT(I:I) = CHAR(ICHAR(INPUT(I:I)) - ICHAR('A') + ICHAR('a'))
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_POST(FILENAME,FILEOPEN,IER,SUBJECT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLNEWS.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /MSGID/ MESSAGE_ID
+	CHARACTER*256 MESSAGE_ID
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /FOLLOWUP/ FOLLOWUP
+	CHARACTER*128 FOLLOWUP
+
+	COMMON /ZONE/ ZONE,LZONE
+	CHARACTER ZONE*4
+
+	COMMON /LOCALPOST/ LOCAL_POST
+	DATA LOCAL_POST /.FALSE./
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	COMMON /SENDER/ SENDER_LINE
+	CHARACTER*256 SENDER_LINE
+
+	COMMON /TEMP_INPUT/ GROUP_TEMP
+	CHARACTER GROUP_TEMP*256
+
+	COMMON /HEADER/ HEADER
+
+        COMMON /MAIL_INFO/ USE_INFROM
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	CHARACTER*(*) FILENAME,SUBJECT
+
+	CHARACTER RESPONSE*4
+
+	CHARACTER TODAY*24,UNAME*132
+	DATA UNAME /'()'/
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	COMMON /NEWS2BULL/ NEWS2BULL
+
+	DIMENSION NOW(2)
+
+	IER = 1
+
+	CREATE = FILENAME(:8).EQ.'newgroup'
+
+	IF (FILENAME.NE.'cancel') THEN
+	   IF (.NOT.FILEOPEN) THEN
+	      OPEN (UNIT=3,FILE=FILENAME,STATUS='OLD',IOSTAT=IER1)
+	      IF (IER1.NE.0) RETURN
+	   ELSE
+	      REWIND (UNIT=3)
+	   END IF
+
+	   IER1 = 0
+	   DO WHILE (IER1.EQ.0)
+	      READ (3,'(A)',IOSTAT=IER1) BUFFER
+	      IF (IER1.NE.0) GO TO 900
+	      IF (TRIM(BUFFER).GT.0) IER1 = 1
+	   END DO
+
+	   REWIND (UNIT=3)
+	END IF
+
+	IER = SYS$GETTIM(NOW)
+	CALL CONVERT_TO_GMT(NOW)
+	IER = SYS$ASCTIM(,TODAY,NOW,)
+
+	NEWS_MSGID = TODAY(:2)//TODAY(4:6)//TODAY(10:11)//'.'//
+     &		TODAY(13:14)//TODAY(16:17)//TODAY(19:20)//TODAY(22:23)
+	IF (NEWS_MSGID(:1).EQ.' ') NEWS_MSGID = NEWS_MSGID(2:)
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   IF (.NOT.NEWS_LOGIN()) GO TO 900
+	   IF (.NOT.NEWS_WRITE('POST')) GO TO 900
+	   IF (.NOT.NEWS_READ()) GO TO 900
+	   IF (BUFFER(:3).NE.'340') THEN
+	      WRITE (6,'('' ERROR: Posting not allowed.'')')
+	      GO TO 900
+	   END IF
+	ELSE
+	   I = INDEX(NEWS_MSGID,'.')
+	   LENGTH = 0
+	   OPEN (UNIT=8,FILE=NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//
+     &		NEWS_MSGID(:I-1)//
+     &		NEWS_MSGID(I+1:TRIM(NEWS_MSGID))//'.POST',IOSTAT=IER,
+     &		STATUS='NEW',DISPOSE='DELETE',RECL=256)
+	   IF (IER.NE.0) RETURN
+	   LOCAL_POST = .TRUE.
+	   CALL INIT_QUEUE(GROUP_LIST1,FOLDER)
+	   GROUP_LIST = GROUP_LIST1
+	END IF
+
+	IF (LPATH.EQ.0) CALL GET_PATHNAME
+
+
+	IF (FILENAME.EQ.'cancel') THEN 
+	   IF (.NOT.NEWS_WRITE('Newsgroups: junk')) GO TO 900
+	ELSE IF (REMOTE_SET.GE.3.OR.CREATE.OR.NEWS_FEED()) THEN
+	   IF (CREATE) THEN
+	      INPUT = 'Newsgroups: '//FILENAME(10:TRIM(FILENAME))
+	   ELSE IF (NEWS_FEED()) THEN
+	      INPUT = 'Newsgroups: '//FOLDER1_DESCRIP
+	   ELSE IF (TRIM(NEWSGROUPS).GT.0.AND.INCMD(:2).EQ.'RE') THEN
+	      IF (TRIM(FOLLOWUP).EQ.0) THEN
+		 INPUT = 'Newsgroups: '//NEWSGROUPS
+		 IF (INDEX(NEWSGROUPS,',').GT.0) THEN
+		    WRITE (6,'('' Warning: Original message was cross'',
+     &                       ''posted to the following news groups:'')')
+		    DO I=1,TRIM(NEWSGROUPS),PAGE_WIDTH
+                       WRITE (6,'(1X,A)') NEWSGROUPS(I:
+     &			I-1+MIN(PAGE_WIDTH,TRIM(NEWSGROUPS(I:))))
+		    END DO
+		    CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &			'Type Y if you want your reply crossposted also, '//
+     &			'N for no: (default = Y) ')
+		    IF (RESPONSE(:1).EQ.'n'.OR.RESPONSE(:1).EQ.'N') THEN
+		       INPUT = 'Newsgroups: '//FOLDER_NAME
+		    END IF
+		 END IF
+	      ELSE
+		 INPUT = 'Newsgroups: '//FOLLOWUP
+	      END IF
+	   ELSE
+	      INPUT = 'Newsgroups: '//FOLDER_NAME
+	   END IF
+	   IF (FILENAME.NE.'cancel'.AND..NOT.CREATE.AND.
+     &	       .NOT.NEWS_FEED()) THEN
+	      NGROUPS = 0
+	      IF (BTEST(FOLDER_FLAG,8)) THEN
+		 CALL WRITE_QUEUE(%VAL(GROUP_LIST),GROUP_LIST,FOLDER)
+		 NGROUPS = NGROUPS + 1
+	      END IF
+	      IF (CLI$PRESENT('GROUPS')) THEN
+		 CALL OPEN_BULLNEWS_SHARED
+		 FLEN = 0
+		 DO WHILE (CLI$GET_VALUE('GROUPS',GROUP_TEMP))
+		    IER = SYS_TRNLNM(GROUP_TEMP,GROUP_TEMP)
+		    DO WHILE (TRIM(GROUP_TEMP).GT.0)
+		       COMMA = INDEX(GROUP_TEMP,',')
+		       IF (COMMA.GT.0) THEN
+			  FOLDER1_NAME = GROUP_TEMP(1:COMMA-1)
+			  GROUP_TEMP = GROUP_TEMP(COMMA+1:)
+		       ELSE
+			  FOLDER1_NAME = GROUP_TEMP
+			  GROUP_TEMP = ' '
+		       END IF
+		       CALL LOWERCASE(FOLDER1_NAME)
+		       FLEN = TRIM(FOLDER1_NAME)
+		       CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &			(FOLDER1_NAME(:FLEN),IER1)
+		       IF (IER1.EQ.0.AND..NOT.BTEST(FOLDER1_FLAG,9)
+     &			   .AND.TRIM(INPUT)+FLEN+1.LE.LEN(INPUT).AND.
+     &			   INDEX(INPUT,FOLDER1_NAME(:FLEN)//',').EQ.0.AND.
+     &			   INPUT(:TRIM(INPUT)).NE.FOLDER1_NAME(:FLEN)) THEN
+			  INPUT = INPUT(:TRIM(INPUT))//
+     &				  ','//FOLDER1_NAME(:FLEN)
+			  IF (BTEST(FOLDER1_FLAG,8).AND.LOCAL_POST) THEN
+			     CALL WRITE_QUEUE(%VAL(GROUP_LIST),
+     &				GROUP_LIST,FOLDER1)
+			     NGROUPS = NGROUPS + 1
+			  END IF
+		       ELSE
+			  WRITE (6,'(1X,A,'' is not a valid news group.'')')
+     &				FOLDER1_NAME(:FLEN)
+			  CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &			   'Do you still want to specify it? (default = Y) ')
+			  IF (RESPONSE(:1).NE.'n'.AND.
+     &			      RESPONSE(:1).NE.'N') THEN
+			     INPUT = INPUT(:TRIM(INPUT))//
+     &				  ','//FOLDER1_NAME(:FLEN)
+			  END IF
+		       END IF
+		    END DO
+		 END DO
+		 CALL CLOSE_BULLNEWS
+	      END IF
+	   END IF
+	   IF (.NOT.NEWS_WRITE(INPUT(:TRIM(INPUT)))) GO TO 900
+	END IF
+	ATSIGN = INDEX(PATHNAME,'@')
+	PCSIGN = INDEX(PATHNAME,'%')
+	CALL LOWERCASE(USERNAME)
+	IF (FILENAME.EQ.'cancel'.AND.SUBJECT(:6).EQ.'CanceL') THEN
+	   IF (.NOT.NEWS_WRITE('Path: cyberspam!usenet')) GO TO 900
+	ELSE
+	   IF (PCSIGN.GT.0) THEN
+	      IF (.NOT.NEWS_WRITE('Path: '//PATHNAME(ATSIGN+1:LPATH)//'!'
+     &	        //PATHNAME(PCSIGN+1:ATSIGN-1)//'!'
+     &	        //USERNAME(:TRIM(USERNAME)))) GO TO 900
+	   ELSE
+	      IF (.NOT.NEWS_WRITE('Path: '//PATHNAME(ATSIGN+1:LPATH)//'!'
+     &	        //USERNAME(:TRIM(USERNAME)))) GO TO 900
+	   END IF
+	END IF
+	IF (UNAME.EQ.'()') CALL GET_UNAME(UNAME)
+
+	IF (FILENAME.NE.'cancel') THEN
+	   FROM_LINE = USERNAME(:TRIM(USERNAME))//PATHNAME(:LPATH)//
+     &			UNAME(:TRIM(UNAME))
+	   IF (USE_INFROM) THEN
+	      IF (INDEX(INFROM,'::').GT.0) THEN
+		 IF (INDEX(INFROM,' ').GT.0) 
+     &		    INFROM = INFROM(:INDEX(INFROM,' ')-1)
+		 INFROM = INFROM(INDEX(INFROM,'::')+2:TRIM(INFROM))//
+     &		      	  PATHNAME(:LPATH)
+	      ELSE IF (INDEX(INFROM,'@').EQ.0) THEN 
+		 INFROM = INFROM(:TRIM(INFROM))//PATHNAME(:LPATH)
+	      END IF
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED').AND.
+     &	            SYS_TRNLNM('MX_REPLY_TO',INFROM)) THEN
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED').AND.
+     &	            SYS_TRNLNM('PMDF_REPLY_TO',INFROM)) THEN
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE IF (SYS_TRNLNM('MULTINET_ROOT','DEFINED').AND.  
+     &	            SYS_TRNLNM('MULTINET_SMTP_REPLY_TO',INFROM)) THEN
+	      IF (.NOT.NEWS_WRITE('From: '//INFROM(:TRIM(INFROM))))
+     &	         GO TO 900
+	      IF (.NOT.NEWS_WRITE('Sender: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   ELSE
+	      IF (.NOT.NEWS_WRITE('From: '//FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   END IF
+	   CALL STR$UPCASE(FROM_LINE,FROM_LINE)
+	   FROM_LINE = FROM_LINE(:TRIM(USERNAME)+LPATH)//UNAME(:TRIM(UNAME))
+	   CALL STR$UPCASE(USERNAME,USERNAME)
+	ELSE IF (REMOTE_SET.EQ.3) THEN
+	   IF (SENDER_LINE.NE.' ') THEN 
+	      IF (.NOT.NEWS_WRITE(SENDER_LINE(:TRIM(SENDER_LINE))))
+     &	         GO TO 900
+	   ELSE
+	      IF (.NOT.NEWS_WRITE(FROM_LINE(:TRIM(FROM_LINE))))
+     &	         GO TO 900
+	   END IF
+	ELSE
+	   HEADER_SAVE = HEADER
+	   HEADER = .TRUE.
+	   CALL OPEN_BULLFIL_SHARED
+	   ILEN = LINE_LENGTH + 1
+	   DO WHILE (ILEN.GT.0)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      ILEN = TRIM(INPUT)
+	      IF (INPUT(:5).EQ.'From:') THEN
+		 GROUP_TEMP = INPUT
+	      ELSE IF (INPUT(:7).EQ.'Sender:') THEN
+		 GROUP_TEMP = 'From:'//INPUT(8:)
+		 ILEN = 0
+	      END IF
+	   END DO
+	   ILEN = TRIM(GROUP_TEMP)
+	   IF (ILEN.NE.0) THEN
+	      IF (.NOT.NEWS_WRITE(GROUP_TEMP(:ILEN))) RETURN
+	   END IF
+	   CALL CLOSE_BULLFIL
+	   HEADER = HEADER_SAVE
+	END IF
+
+	IF (FILENAME.EQ.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Subject: cancel <'//
+     &	    MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) GO TO 900
+	ELSE IF (TRIM(SUBJECT).EQ.0) THEN
+	   IF (.NOT.NEWS_WRITE('Subject: (none)'))
+     &	      GO TO 900
+	ELSE
+	   IF (.NOT.NEWS_WRITE('Subject: '//SUBJECT(:TRIM(SUBJECT))))
+     &	      GO TO 900
+	END IF
+	SUBJECT_LINE = SUBJECT
+
+	IF (INCMD(:2).EQ.'RE') THEN
+	   IF (.NOT.NEWS_WRITE('References: '//REFERENCES(:LREF)))
+     &	      GO TO 900
+	END IF
+
+	IF (NGROUPS.GT.0) THEN
+	   FROM = USERNAME
+	   DESCRIP = SUBJECT
+	END IF
+
+	IF (FILENAME.NE.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Message-ID: <'//NEWS_MSGID(:
+     &	       TRIM(NEWS_MSGID))//PATHNAME(:LPATH)//'>')) GO TO 900
+	ELSE
+	   IF (.NOT.NEWS_WRITE('Message-ID: <cancel.'//
+     &	       MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) GO TO 900
+	END IF
+	NEWS_MSGID = NEWS_MSGID(:TRIM(NEWS_MSGID))//PATHNAME(:LPATH)
+
+	IF (LORGAN.EQ.0) THEN
+	   IF (SYS_TRNLNM('BULL_NEWS_ORGANIZATION','DEFINED')) THEN
+	      IER1 = SYS_TRNLNM('BULL_NEWS_ORGANIZATION',ORGANIZATION)
+	   END IF
+	   LORGAN = TRIM(ORGANIZATION)
+	END IF
+
+	IF (FILENAME.NE.'cancel'.AND.LORGAN.GT.0) THEN
+	   IF (.NOT.NEWS_WRITE('Organization: '//ORGANIZATION(:LORGAN)))
+     &		GO TO 900
+	ELSE IF (FILENAME.EQ.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Organization: cancel'))
+     &		GO TO 900
+	END IF
+
+	IF (.NOT.USE_INFROM.OR.COMPARE_DATE(TODAY(:11),DATE).GT.13) THEN
+	   DATE = TODAY(:11)
+	   TIME = TODAY(13:20)//'.00'
+	   TODAY = TODAY(:2)//' '//TODAY(4:6)//' '//TODAY(8:20)
+	   IF (TODAY(1:1).EQ.' ') TODAY = TODAY(2:)
+	   IF (.NOT.NEWS_WRITE('Date: '//TODAY(:TRIM(TODAY))//' '//
+     &		ZONE(:LZONE))) GO TO 900
+	ELSE
+	   CALL CONVERT_TO_GMT(MSG_BTIM)
+	   IER = SYS$ASCTIM(,TODAY,MSG_BTIM,)
+	   DATE = TODAY(:11)
+	   TIME = TODAY(13:20)//'.00'
+	   TODAY = DATE(:2)//' '//DATE(4:6)//' '//DATE(8:)
+	   IF (TODAY(1:1).EQ.' ') TODAY = TODAY(2:)
+	   IF (.NOT.NEWS_WRITE('Date: '//TODAY(:TRIM(TODAY))//' '//
+     &		TIME(:8)//' '//ZONE(:LZONE))) GO TO 900
+	END IF
+
+	INPUT_HEADER = .FALSE.
+
+	IF (.NOT.(CREATE.OR.FILENAME.EQ.'cancel')) THEN
+	   EXPR = NEWS_FEED().OR.USE_INFROM
+	   IF (.NOT.EXPR) EXPR = CLI$PRESENT('EXPIRATION')
+	   IF (EXPR) THEN
+	      I = INDEX(EXDATE,'-')
+	      IF (.NOT.NEWS_WRITE('Expires: '//EXDATE(FIRST_ALPHA(EXDATE):2)
+     &		   //' '//EXDATE(I+1:I+3)//' '//EXDATE(I+7:TRIM(EXDATE))
+     &		   //' '//EXTIME(:8)//' '//ZONE(:LZONE)))
+     &		   GO TO 900
+	   ELSE IF (REMOTE_SET.EQ.4) THEN
+	      IF ( FOLDER_BBEXPIRE.GT.0) THEN
+		 CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      ELSE
+		 CALL GET_EXDATE(EXDATE,NEWS_EXPIRE_DEFAULT)
+	      END IF
+	      EXTIME = '00:00:00.00'
+	   END IF
+	   IF (.NOT.NEWS_FEED()) THEN
+	      IF (CLI$GET_VALUE('FOLLOWUP',GROUP_TEMP)) THEN
+	         CALL LOWERCASE(GROUP_TEMP)
+	         IF (.NOT.NEWS_WRITE('Followup-To: '
+     &		     //GROUP_TEMP(:TRIM(GROUP_TEMP)))) GO TO 900
+	      END IF
+	   END IF
+	END IF
+
+	IF (CREATE) THEN
+	   IF (.NOT.NEWS_WRITE('Control: '//FILENAME(:TRIM(FILENAME))))
+     &		 RETURN
+	END IF
+
+	IF (NEWS_FEED().OR.NEWS2BULL) THEN
+	   IF (.NOT.NEWS_WRITE('X-Newsreader: News2bull')) GO TO 900
+	END IF
+
+	IF (FILENAME.EQ.'cancel') THEN
+	   IF (.NOT.NEWS_WRITE('Control: cancel <'
+     &		//MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) RETURN
+	   IF (.NOT.NEWS_WRITE(' ')) RETURN
+	   IF (.NOT.NEWS_WRITE('cancel <'
+     &		//MESSAGE_ID(:TRIM(MESSAGE_ID))//'>')) RETURN
+	   IF (SUBJECT(:6).EQ.'CanceL') THEN
+	      IF (SUBJECT.EQ.'CanceL') THEN
+	         WRITE (6,1055)
+	         ILEN = LINE_LENGTH + 1		! Length of input line
+	         DO WHILE (ILEN.GE.0)		! Input until no more input
+	            CALL GET_LINE(INPUT,ILEN)	! Get input line
+	            IF (ILEN.GT.LINE_LENGTH) THEN  ! Input line too long
+		       WRITE(6,'('' ERROR: Input line length > '',I,
+     &			      ''.  Reinput:'')') LINE_LENGTH
+	            ELSE IF (ILEN.GE.0) THEN	! If good input line entered
+	    	       IF (.NOT.NEWS_WRITE(INPUT(:ILEN))) RETURN
+	            END IF
+	         END DO
+	      ELSE
+		 IF (.NOT.NEWS_WRITE(SUBJECT(7:TRIM(SUBJECT)-6))) RETURN
+	      END IF
+	   END IF
+	   IF (.NOT.NEWS_WRITE('.')) RETURN
+	   IF (REMOTE_SET.EQ.3) THEN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (BUFFER(:3).EQ.'240') IER = 0
+	   ELSE
+	      CLOSE (UNIT=8,STATUS='SAVE')
+	      IER = 0
+	   END IF
+	   CALL STR$UPCASE(USERNAME,USERNAME)
+	   LOCAL_POST = .FALSE.
+	   RETURN
+	END IF
+
+	IF (.NOT.INPUT_HEADER) THEN
+	   IF (.NOT.NEWS_WRITE(' ')) GO TO 900
+	END IF
+
+	IER1 = 0
+	DO WHILE (IER1.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER1) ILEN,BUFFER
+	   IF (BUFFER(:ILEN).EQ.'.') THEN
+	      BUFFER = '..'
+	      ILEN = 2
+	   END IF
+	   IF (IER1.EQ.0) THEN
+	      IF (.NOT.NEWS_WRITE(BUFFER(:ILEN))) GO TO 900
+	   END IF
+	END DO
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   IF (.NOT.NEWS_WRITE('.')) GO TO 900
+	   IF (.NOT.NEWS_READ()) GO TO 900
+	   IF (BUFFER(:3).EQ.'240') THEN
+	      IER = 0
+	   ELSE
+	      WRITE (6,'('' ERROR: Server rejected your posting:'')')
+	      WRITE (6,'(1X,A)') BUFFER(SB:MIN(79+SB,EB))
+	      IF (INDEX(BUFFER(SB:EB),'new text').GT.0) THEN
+		 WRITE (6,'('' Use /INDENT to change indentation'',$)')
+		 WRITE (6,'(''+ character. See Manager for permanent'',$)')
+		 WRITE (6,'(''+ change.'')')
+	      END IF
+	   END IF
+	ELSE
+	   LENGTH = (LENGTH+127)/128
+	   GROUP_LIST = GROUP_LIST1
+	   FOLDER_NUMBER_SAVE = FOLDER_NUMBER
+	   SAVE_BULL_POINT = BULL_POINT
+	   OLD_NBULL = NBULL
+	   DO I=NGROUPS,1,-1
+	      CALL READ_QUEUE(%VAL(GROUP_LIST),GROUP_LIST,FOLDER1)
+	      FOLDER_NUMBER = -1
+	      OLD_NBULL = NBULL
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (IER) THEN
+		 CALL ADD_LOCAL_NEWS(8)
+		 CALL ADD_TAG(IER,2)
+		 IF (NEWS_FIND_SUBSCRIBE().LT.FOLDER_MAX) THEN
+		    CALL NEWS_GET_NEWEST_MESSAGE(IER1)
+		    IF (IER1.EQ.0.OR.IER1.EQ.OLD_NBULL+1) THEN
+		       CALL NEWS_UPDATE_NEWEST_MESSAGE(OLD_NBULL+1)
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (FOLDER_NUMBER.NE.FOLDER_NUMBER_SAVE) THEN
+	      FOLDER_NUMBER = FOLDER_NUMBER_SAVE
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	   END IF
+	   BULL_POINT = SAVE_BULL_POINT
+	   IF (.NOT.NEWS_WRITE('.')) GO TO 900
+	   CLOSE (UNIT=8,STATUS='SAVE')
+	   IER = 0
+	END IF
+
+900	IF (FILENAME.NE.'cancel'.AND..NOT.FILEOPEN) CLOSE (UNIT=3)
+	CALL STR$UPCASE(USERNAME,USERNAME)
+
+	LOCAL_POST = .FALSE.
+
+1055	FORMAT(' State reason for deleting message not owned by you:')
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_PATHNAME
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	IF (NEWS_GETHOSTNAME(PATHNAME).EQ.-1) THEN
+	   IER = SYS_TRNLNM_SYSTEM('MX_NODE_NAME',PATHNAME)
+	   IF (.NOT.IER)
+     &		IER = SYS_TRNLNM_SYSTEM('ARPANET_HOST_NAME',PATHNAME)
+	   IF (.NOT.IER)
+     &		IER = SYS_TRNLNM_SYSTEM('INTERNET_HOST_NAME',PATHNAME)
+	   IF (.NOT.IER) THEN
+	      WRITE (6,'('' ERROR: Cannot find local host name.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	IF (ALPHA(PATHNAME(:1))) PATHNAME = '@'//PATHNAME
+
+	CALL LOWERCASE(PATHNAME)
+	LPATH = TRIM(PATHNAME)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST_NEWS(NAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) NAME
+
+	TEST_NEWS = .FALSE.
+	MAYBE_NEWS = .FALSE.
+
+	DO I=1,LEN(NAME)
+	   IF (NAME(I:I).GE.'A'.AND.NAME(I:I).LE.'Z') RETURN
+	   IF (NAME(I:I).GE.'a'.AND.NAME(I:I).LE.'z') MAYBE_NEWS = .TRUE.
+	END DO
+
+	TEST_NEWS = MAYBE_NEWS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_LOCAL_NEWS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /LOCAL_UPDATE/ LOCAL_UPDATE1
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER CNUM*4,NUMBER*8
+	EQUIVALENCE (CNUM,NUM)
+
+	CALL INIT_QUEUE(LOCAL_UPDATE1,CNUM)
+
+	LOCAL_UPDATE = LOCAL_UPDATE1
+
+	CALL READ_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,CNUM)
+	IF (NUM.EQ.0) RETURN
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	DO WHILE (NUM.GT.0)
+	   CALL READ_FOLDER_FILE_KEYNUM_TEMP(NUM,IER)
+	   IF (IER.EQ.0) THEN
+	      CALL CLOSE_BULLNEWS
+	      CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      LAST = F1_NBULL
+	      FIRST = F1_START
+	      IF (IER.EQ.0) THEN
+		 FOLDER_COM = FOLDER1_COM
+		 REMOTE_SET = 3
+		 CALL OPEN_BULLDIR_SHARED
+		 INCMD = 'READ'	  ! REMOTE_GET_HEADER uses NEXT otherwise
+		 I = F_LAST + 1
+		 IER = I - 1
+		 DO WHILE (I.NE.IER.AND.I.LE.LAST)
+		    CALL READDIR(I,IER)
+		    I = I + 1
+		 END DO
+		 CALL CLOSE_BULLDIR
+		 CALL OTS$CVT_L_TI(I-1,NUMBER,,,)
+		 INCMD = 'COPY/ORIGINAL '//FOLDER(:TRIM(
+     &			FOLDER))//' '//NUMBER//'-LAST'
+		 CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+		 CALL MOVE(.FALSE.)
+		 CALL OPEN_BULLNEWS_SHARED
+		 IF (REMOTE_SET.EQ.4) THEN
+		    NEW_F_COUNT = F_COUNT
+		    NEW_NEWS_F_END = NEWS_F_END
+		    CALL READ_FOLDER_FILE_KEYNUM(NUM,IER)
+		    CALL GET_MSGKEY(NEWEST_EXBTIM,NEWS_F_EXPIRED_DATE)
+		    CALL COPY2(F_NEWEST_BTIM,NEWEST_MSGBTIM)
+		    IF (F_START.EQ.0.AND.NBULL.GT.0) F_START = 1
+		    IF (NEW_NEWS_F_END.GT.NEWS_F_END) THEN
+		       NEWS_F_END = NEW_NEWS_F_END
+		       F_NBULL = NEW_NEWS_F_END
+		       F_COUNT = NEW_F_COUNT
+		    END IF
+		    F_LAST = LAST
+		    NEWS_F_FIRST = FIRST
+		    CALL REWRITE_FOLDER_FILE(IER)
+		 END IF
+	      END IF
+	   END IF
+	   CALL READ_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,CNUM)
+	   IF (NUM.EQ.0) THEN
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS2BULL(RECLAIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLCP_NEWS/ BULLCP_NEWS
+	DATA BULLCP_NEWS /.FALSE./
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER FOLDER_SAVE*44,BBOARD_SAVE*12
+
+	CHARACTER*8 NUMBER
+
+	DIMENSION NOW(2)
+
+	BULLCP_NEWS = .TRUE.
+
+	IER = SYS$GETTIM(NOW)
+
+	CALL ALLPRIV
+
+	CALL DELETE_EXPIRED_NEWS(RECLAIM)
+
+	IF (RECLAIM) CALL EXIT
+
+	CALL SEND_POST
+	IF (ALT_SET()) CALL UNSET_ALT
+
+	CALL NEWS_LIST
+
+	CALL UPDATE_LOCAL_NEWS
+
+	CALL INIT_QUEUE(FOLDER_Q1,FOLDER_COM)
+
+	FOLDER_Q = FOLDER_Q1
+
+	CALL OPEN_BULLFOLDER_SHARED             ! Get folder file
+
+	NUM_FOLDERS = 0
+	IER = 0
+	DO WHILE (IER.EQ.0)                     ! Find folders with news feed
+	   CALL READ_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) THEN
+	      IF (NEWS_FEED()) THEN
+		 NUM_FOLDERS = NUM_FOLDERS + 1
+		 CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFOLDER                   ! We don't need file anymore
+
+	IF (NUM_FOLDERS.EQ.0.OR..NOT.NEWS_LOGIN()) CALL EXIT
+
+	FOLDER_Q = FOLDER_Q1
+	POINT_FOLDER = 0
+	DO WHILE (POINT_FOLDER.LT.NUM_FOLDERS)
+	   POINT_FOLDER = POINT_FOLDER + 1
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   FOLDER_SAVE = FOLDER
+	   BBOARD_SAVE = FOLDER_BBOARD
+	   FOLDER_DESCRIP = FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,'<')+1:)
+	   FOLDER_DESCRIP = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,'>')-1)
+	   IF (IER) THEN
+	      SAVE_LAST = F_LAST
+	      CALL OPEN_BULLNEWS_SHARED
+	      FOLDER1 = FOLDER_DESCRIP(:TRIM(FOLDER_DESCRIP))
+	      CALL READ_FOLDER_FILE_KEYNAME
+     &		(FOLDER_DESCRIP(:TRIM(FOLDER_DESCRIP)),IER)
+	      CALL CLOSE_BULLNEWS
+	      FOLDER1_DESCRIP = FOLDER_DESCRIP
+	      IF (IER.EQ.0) CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      IF (IER.EQ.0) FOLDER_COM = FOLDER1_COM
+	      IF (IER.EQ.0.AND.BBOARD_SAVE.EQ.'NONE') THEN
+		 SAVE_LAST = F_NBULL
+		 CALL OPEN_BULLFOLDER
+		 CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER1)
+		 F_LAST = SAVE_LAST
+		 FOLDER_BBOARD = 'NONEFEED'
+		 CALL REWRITE_FOLDER_FILE(IER1)
+		 CALL CLOSE_BULLFOLDER
+	      ELSE IF (IER.EQ.0.AND.F_NBULL.NE.SAVE_LAST.AND.
+     &		  F_NBULL.GE.F_START) THEN
+	         IF (FOLDER_BBOARD.EQ.'NONEFEED') THEN
+		    CALL SETUSER('SYSTEM')
+	         ELSE
+		    CALL SETUSER(FOLDER_BBOARD)
+	         END IF
+		 REMOTE_SET = 3
+		 IF (SAVE_LAST.GT.F_NBULL.AND.F_START.EQ.1)
+     &			SAVE_LAST = F_START-1
+		 SAVE_LAST = MAX(F_START-1,SAVE_LAST)
+		 CALL OTS$CVT_L_TI(SAVE_LAST+1,NUMBER,,,)
+		 INCMD = 'COPY/LOCAL/ORIGINAL '//FOLDER_SAVE(:TRIM(
+     &			FOLDER_SAVE))//' '//NUMBER//'-LAST'
+		 SAVE_LAST = F_NBULL
+		 CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+		 CALL MOVE(.FALSE.)
+		 CALL OPEN_BULLFOLDER
+		 CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER1)
+		 IF (IER1.EQ.0) THEN
+		    F_LAST = SAVE_LAST
+		    CALL REWRITE_FOLDER_FILE(IER1)
+		 END IF
+		 CALL CLOSE_BULLFOLDER
+	         CALL SETUSER(USERNAME)
+	      END IF
+	   END IF
+	END DO
+
+	CALL EXIT
+	END
+
+
+
+	SUBROUTINE DATE_TIME(TIME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MONTHS/ MONTH
+	CHARACTER*36 MONTH
+	DATA MONTH/'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'/
+
+	CHARACTER*(*) TIME
+
+	NMONTH = (INDEX(MONTH,TIME(4:6))+2)/3
+
+	IF (TIME(1:1).EQ.' ') TIME(1:1) = '0'
+
+	TIME = TIME(10:11)//CHAR(ICHAR('0')+NMONTH/10)//CHAR(ICHAR('0')+
+     &		 MOD(NMONTH,10))//TIME(1:2)//' '//TIME(13:14)//
+     &		 TIME(16:17)//TIME(19:20)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ALLPRIV
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	PROCPRIV(1) = -1
+	PROCPRIV(2) = -1
+	NEEDPRIV(1) = -1
+	NEEDPRIV(2) = -1
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_NEW_FOLDER
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1) NEWS_FOLDER_COM
+
+	NEWS_FOLDER1 = FOLDER1
+	NEWS_FOLDER1_DESCRIP = FOLDER1_DESCRIP(26:)
+
+	DO WHILE (IER.EQ.0)
+	   READ (7,IOSTAT=IER,KEYEQ=NEWS_F_COUNT,KEYID=1)
+	   IF (IER.EQ.0) NEWS_F_COUNT = NEWS_F_COUNT + 1
+	END DO
+
+	NEWS_FOLDER1_NUMBER = NEWS_F_COUNT
+	CALL SYS_BINTIM('-',NEWS_F1_NEWEST_BTIM)
+	WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+
+	READ (7,KEYEQ=1000,KEYID=1) NEWS_FOLDER1_COM
+	NEWS_F1_COUNT = NEWS_F_COUNT
+	REWRITE (7) NEWS_FOLDER1_COM
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SUBSCRIBE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.LT.3) THEN
+	   WRITE (6,'('' ERROR: Selected folder is not a news folder.'')')
+	   RETURN
+	END IF
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.NEWS_FOLDER_NUMBER.AND.
+     &		LAST_NEWS_READ2(1,I).NE.0.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: Cannot subscribe.  You have '',
+     &		    '' reached the news folder limit of '',I,''.'')')
+     &		    FOLDER_MAX-1
+	   RETURN
+	ELSE IF (LAST_NEWS_READ2(1,I).EQ.NEWS_FOLDER_NUMBER) THEN
+	   WRITE (6,'('' You are already subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   RETURN
+	ELSE
+	   WRITE (6,'('' You are now subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	END IF
+
+	CALL UPDATE_USERINFO
+
+	CALL OPEN_BULLNEWS_SHARED
+	DO J=I,1,-1
+	   IF (J.GT.1) THEN
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(
+     &		 ZEXT(LAST_NEWS_READ2(1,J-1)),IER)
+	      IF (FOLDER_DESCRIP.LT.FOLDER1_DESCRIP) THEN
+		 CALL COPY2(LAST_NEWS_READ(1,J),LAST_NEWS_READ(1,J-1))
+	      END IF
+	   END IF
+	   IF (FOLDER_DESCRIP.GT.FOLDER1_DESCRIP.OR.J.EQ.1) THEN
+	      LAST_NEWS_READ2(1,J) = NEWS_FOLDER_NUMBER
+	      IF (F_START.LE.F_NBULL) THEN
+		 LAST_NEWS_READ2(2,J) = MIN(8191,F_NBULL-(F_START-1))
+		 LAST_NEWS_READ(2,J) = F_START - 1
+	      ELSE
+		 LAST_NEWS_READ2(2,J) = 0
+		 LAST_NEWS_READ(2,J) = F_NBULL
+	      END IF
+	      CALL CLOSE_BULLNEWS
+	      CALL LIB$MOVC3(8*FOLDER_MAX,LAST_NEWS_READ,OLD_LAST_NEWS_READ)
+	      CALL UPDATE_USERINFO_NEWS_ALWAYS
+	      RETURN
+	   END IF
+	END DO
+
+	END
+
+
+
+
+
+	SUBROUTINE UNSUBSCRIBE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_EXPIRED
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: You are not subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLINF_SHARED
+	DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY='*PERM',IOSTAT=IER) TEMP_USER,INF_REC
+	END DO
+	IF (IER.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      INF_REC(1,I) = 0
+	      INF_REC(2,I) = 0
+	   END DO
+	END IF
+	CALL CLOSE_BULLINF
+
+	I = 1
+	DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	IF (I.LE.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: Folder is permanent and cannot not be'',
+     &		      '' unsubscribed.'')')
+	   RETURN
+	END IF
+
+	WRITE (6,'('' You are now no longer subscribed to '',A,''.'')')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+
+	CALL UPDATE_USERINFO
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	DO J=I,FOLDER_MAX-2
+	   CALL COPY2(LAST_NEWS_READ(1,J),LAST_NEWS_READ(1,J+1))
+	END DO
+
+	LAST_NEWS_READ(1,FOLDER_MAX-1) = 0
+	LAST_NEWS_READ(2,FOLDER_MAX-1) = 0
+
+	CALL FREE_TAGS(I)
+
+	IF (NINCLUDE.GT.0) THEN
+	   WRITE (6,'('' Note: Excludes and/or '',
+     &		      ''threads exist for this group.'')')
+	   WRITE (6,'('' Type EXCLUDE/DISABLE/ALL to remove them.'')')
+	END IF
+
+	CALL LIB$MOVC3(8*FOLDER_MAX,LAST_NEWS_READ,OLD_LAST_NEWS_READ)
+
+	CALL UPDATE_USERINFO_NEWS_ALWAYS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_GET_NEWEST_MESSAGE(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IER = LAST_NEWS_READ(2,I) + 1
+
+	IF (IER.EQ.0) IER = 1           ! None read yet.
+
+	IF (I.GT.FOLDER_MAX-1.OR.IER.GT.F_NBULL) THEN
+	   IER = 0
+	   RETURN
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_GET_NEWEST_MESSAGE1(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE1()
+
+	IER = LAST_NEWS_READ(2,I) + 1
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   IER = 0
+	   RETURN
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_UPDATE_NEWEST_MESSAGE(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	IF (NUMBER.GT.LAST_NEWS_READ(2,I).OR.(LAST_NEWS_READ(2,I)
+     &	 .GT.NEWS_F_NBULL.AND.F_START.LE.F_NBULL)) THEN
+	   LAST_NEWS_READ(2,I) = NUMBER
+	   LAST_NEWS_READ2(2,I) = MIN(8191,F_NBULL-NUMBER)
+     &			.OR.(LAST_NEWS_READ2(2,I).AND.'E000'X)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE NEWS_GET_SUBSCRIBE(SUBNUM,SUBMSG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (SUBNUM.EQ.0) THEN
+	   COUNT = 0
+	   SUBMSG = LAST_NEWS_READ(2,1)
+	   RETURN
+	ELSE IF (SUBNUM.EQ.-1) THEN
+	   DO J=COUNT,FOLDER_MAX-1
+	      CALL COPY2(LAST_NEWS_READ(1,J),LAST_NEWS_READ(1,J+1))
+	   END DO
+
+	   LAST_NEWS_READ(1,FOLDER_MAX-1) = 0
+	   LAST_NEWS_READ(2,FOLDER_MAX-1) = 0
+	ELSE IF (SUBNUM.GT.0) THEN
+	   COUNT = COUNT + 1
+	END IF
+
+	IF (COUNT.LE.FOLDER_MAX-1) THEN
+	   SUBNUM = LAST_NEWS_READ2(1,COUNT)
+	   SUBMSG = LAST_NEWS_READ(2,COUNT)
+	ELSE
+	   SUBNUM = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS_NEW_NOTIFICATION(MESSAGES)
+C
+C  SUBROUTINE NEWS_NEW_NOTIFICATION
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /LOGIN_BTIM/ LOGIN_BTIM_SAVE(2)
+
+	MESSAGES = .FALSE.
+
+	IF (.NOT.SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) RETURN
+
+	CALL NEWS_GET_SUBSCRIBE(0,MSGNUM)
+
+	CALL OPEN_BULLNEWS_SHARED
+	SUBNUM = 1
+
+	FOLDER_DESCRIP = ' '
+	REORDER = 0
+	DO WHILE (SUBNUM.GT.0)
+	   IER = 1
+	   DO WHILE (SUBNUM.NE.0.AND.IER.NE.0)
+	      CALL NEWS_GET_SUBSCRIBE(SUBNUM,MSGNUM)
+	      FOLDER1_DESCRIP = FOLDER_DESCRIP
+	      IF (SUBNUM.NE.0) THEN
+		 CALL READ_FOLDER_FILE_KEYNUM(SUBNUM,IER)
+		 IF (IER.EQ.0) FOLDER_NUMBER = SUBNUM
+		 UNLOCK 7
+		 IF (FOLDER1_DESCRIP.GT.FOLDER_DESCRIP) REORDER = 1
+		 IF (IER.EQ.0.AND.
+     &			MSGNUM.GT.F_NBULL.AND.F_START.LE.F_NBULL) THEN
+		    CALL NEWS_UPDATE_NEWEST_MESSAGE(F_START-1)
+		 ELSE IF (IER.NE.0) THEN
+		    SUBNUM = -1
+		 ELSE IF (MSGNUM.GE.F_NBULL.OR.F_NBULL.EQ.0.OR.
+     &			  F_START.GT.F_NBULL) THEN
+		    IER = 1
+		 END IF
+	      END IF
+	      IF (IER.EQ.0.AND.SUBNUM.GT.0) THEN
+		 IF (READIT.EQ.1) THEN
+		    IF (.NOT.TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER).AND.
+     &			.NOT.TEST_SET_FLAG(NEWS_FOLDER_NUMBER)) THEN
+		       IER = 1
+		    ELSE IF (.NOT.TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER).OR.
+     &			.NOT.TEST_SET_FLAG(NEWS_FOLDER_NUMBER).OR.
+     &			NEW_FLAG(2).NE.-1) THEN
+		       DIFF = COMPARE_BTIM(LOGIN_BTIM_SAVE,F_NEWEST_BTIM)
+		       IF (DIFF.GT.0) IER = 1
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (READIT.EQ.0.AND.SUBNUM.GT.0) THEN
+	      WRITE (6,'('' There are new messages in folder '',
+     &		  A)') FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	      MESSAGES = .TRUE.
+	   ELSE IF (SUBNUM.GT.0) THEN
+	      IF (TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER)
+     &		  .AND.TEST_SET_FLAG(NEWS_FOLDER_NUMBER)) THEN
+		 WRITE (6,'('' There are new messages in folder ''
+     &		  A)') FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	      ELSE
+		 CALL CLOSE_BULLNEWS
+		 CALL SELECT_FOLDER(.FALSE.,IER1)
+		 IF (IER1) THEN
+		    CALL LOGIN_FOLDER
+		    IF (BULL_POINT.NE.-1) THEN
+		       NEWS_FOLDER_NUMBER = FOLDER_NUMBER
+		       IF (.NOT.TEST_BRIEF_FLAG(NEWS_FOLDER_NUMBER)) THEN
+			  SAVE_BULL_POINT = BULL_POINT
+			  REDO = .TRUE.
+			  DO WHILE (REDO)
+			     REDO = .FALSE.
+			     CALL READNEW(REDO)
+			     IF (REDO) CALL REDISPLAY_DIRECTORY
+			     BULL_POINT = SAVE_BULL_POINT
+			  END DO
+		       END IF
+		    END IF
+		 END IF
+		 CALL OPEN_BULLNEWS_SHARED
+	      END IF
+	   END IF
+	END DO
+
+	IF (REORDER.EQ.1) CALL REORDER_SUBSCRIBE
+
+	CALL CLOSE_BULLNEWS
+
+	RETURN
+	END
+
+
+	SUBROUTINE REORDER_SUBSCRIBE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.0)
+	   I = I + 1
+	END DO
+
+	I = I - 1
+
+	DO I1=1,I-1
+	   DO J=1,I-I1
+	      K = J + 1
+	      S1 = LAST_NEWS_READ2(1,J)
+	      S2 = LAST_NEWS_READ2(1,K)
+	      CALL READ_FOLDER_FILE_KEYNUM(S1,IER)
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(S2,IER1)
+	      IF (IER+IER1.EQ.0.AND.FOLDER1_DESCRIP.LT.FOLDER_DESCRIP) THEN
+		 DO L=1,2
+		    TEMP = LAST_NEWS_READ(L,J)
+		    LAST_NEWS_READ(L,J) = LAST_NEWS_READ(L,K)
+		    LAST_NEWS_READ(L,K) = TEMP
+		 END DO
+	      END IF
+	   END DO
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_SET_FLAG(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (NUMBER.GE.0.AND.NUMBER.LE.FOLDER_MAX-1) THEN
+	   TEST_SET_FLAG = TEST2(SET_FLAG,NUMBER)
+	   RETURN
+	END IF
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	TEST_SET_FLAG = .FALSE.
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	TEST_SET_FLAG = BTEST(LAST_NEWS_READ2(2,I),14)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_BRIEF_FLAG(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (NUMBER.GE.0.AND.NUMBER.LE.FOLDER_MAX-1) THEN
+	   TEST_BRIEF_FLAG = TEST2(BRIEF_FLAG,NUMBER)
+	   RETURN
+	END IF
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	TEST_BRIEF_FLAG = .FALSE.
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	TEST_BRIEF_FLAG = BTEST(LAST_NEWS_READ2(2,I),15)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_NOTIFY_FLAG(NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (NUMBER.GE.0.AND.NUMBER.LE.FOLDER_MAX-1) THEN
+	   TEST_NOTIFY_FLAG = TEST2(NOTIFY_FLAG,NUMBER)
+	   RETURN
+	END IF
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	TEST_NOTIFY_FLAG = .FALSE.
+
+	IF (I.GT.FOLDER_MAX-1) RETURN
+
+	TEST_NOTIFY_FLAG = BTEST(LAST_NEWS_READ2(2,I),13)
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_FIND_SUBSCRIBE()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.NEWS_FOLDER_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	NEWS_FIND_SUBSCRIBE = I
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION NEWS_FIND_SUBSCRIBE1()
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = 1
+	DO WHILE (LAST_NEWS_READ2(1,I).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	NEWS_FIND_SUBSCRIBE1 = I
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS_SET_USER_FLAG(NOTIFY,READNEW,BRIEF)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	I = NEWS_FIND_SUBSCRIBE()
+
+	IF (I.GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: NEWS FOLDER is not subscribed.'')')
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLINF_SHARED
+	DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY='*PERM',IOSTAT=IER1) TEMP_USER,INF_REC
+	END DO
+	IF (IER1.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      INF_REC(1,I) = 0
+	      INF_REC(2,I) = 0
+	   END DO
+	END IF
+	CALL CLOSE_BULLINF
+
+	IP = 1
+	DO WHILE (INF_REC2(1,IP).NE.NEWS_FOLDER_NUMBER
+     &					.AND.IP.LE.FOLDER_MAX-1)
+	   IP = IP + 1
+	END DO
+
+	IER = .TRUE.
+
+	IF (IP.EQ.FOLDER_MAX) THEN
+	   PERM = .FALSE.
+	   IP = 1
+	ELSE
+	   PERM = .TRUE.
+	END IF
+
+	IF (NOTIFY.EQ.0) THEN
+	   IF (PERM.AND.BTEST(INF_REC2(2,IP),13)) THEN
+	      WRITE (6,'('' ERROR: NOTIFY is permanent for this folder.'')')
+	      RETURN
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),13)
+	   END IF
+	ELSE IF (NOTIFY.EQ.1) THEN
+	   LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),13)
+	   RETURN
+	ELSE IF (BRIEF.EQ.0.AND.READNEW.EQ.0.AND.PERM.AND.
+     &	    (BTEST(INF_REC2(2,IP),14).OR.BTEST(INF_REC2(2,IP),15))) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.0.AND.PERM.AND.
+     &	    (BTEST(INF_REC2(2,IP),14).AND.
+     &	    .NOT.BTEST(INF_REC2(2,IP),15))) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.1.AND.PERM.AND.
+     &	    (BTEST(INF_REC2(2,IP),14).XOR.BTEST(INF_REC2(2,IP),15))) THEN
+	   IER = .FALSE.
+	END IF
+
+	IF (IER) THEN
+	   IF (READNEW.EQ.1)
+     &		LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),14)
+	   IF (READNEW.EQ.0)
+     &		LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),14)
+	   IF (BRIEF.EQ.1)
+     &		LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),15)
+	   IF (BRIEF.EQ.0)
+     &		LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),15)
+	ELSE
+	   WRITE (6,'('' ERROR: PERMANENT flags exist for this folder.'')')
+	   WRITE (6,'('' Flags will be set to those permanent settings.'')')
+
+	   IF (BTEST(INF_REC2(2,IP),14)) THEN
+	      LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),14)
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),14)
+	   END IF
+
+	   IF (BTEST(INF_REC2(2,IP),15)) THEN
+	      LAST_NEWS_READ2(2,I) = IBSET(LAST_NEWS_READ2(2,I),15)
+	   ELSE
+	      LAST_NEWS_READ2(2,I) = IBCLR(LAST_NEWS_READ2(2,I),15)
+	   END IF
+	END IF
+
+	CALL UPDATE_USERINFO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_LOCAL_NEWS(UNIT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	COMMON /NEWS_HEADER_INFO/ MSGNUM,SUBJECT_LINE,FROM_LINE
+	CHARACTER*256 FROM_LINE,SUBJECT_LINE
+	CHARACTER*12 MSGNUM
+
+	REWIND UNIT
+
+	CALL SYS_BINTIM(EXDATE//' '//EXTIME,EX_BTIM)
+
+	CALL OPEN_BULLDIR
+	CALL OPEN_BULLFIL
+	CALL SET_BULLFIL_UPDATE
+	OBLOCK = NBLOCK + 1
+	CALL STORE_BULL(TRIM(FROM_LINE)+6,'From: '//
+     &		    FROM_LINE(:TRIM(FROM_LINE)),OBLOCK)
+	IF (TRIM(SUBJECT_LINE).GT.LEN(DESCRIP)) THEN
+	   CALL STORE_BULL(TRIM(SUBJECT_LINE)+6,
+     &		'Subj: '//SUBJECT_LINE(:TRIM(SUBJECT_LINE)),OBLOCK)
+	END IF
+	CALL COPY_BULL(UNIT,1,OBLOCK,IER)
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	   RETURN
+	END IF
+	LENGTH = OCOUNT - (NBLOCK + 1) + 1
+	NBLOCK = NBLOCK + LENGTH + 1
+	SYSTEM = 0
+	CALL ADD_ENTRY
+	CALL CLOSE_BULLFIL
+	CALL UPDATE_NEWS_FOLDER
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_NEWS_FOLDER
+C
+C  SUBROUTINE UPDATE_NEWS_FOLDER
+C
+C  FUNCTION: Updates folder info due to new message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	NEW_NEWS_F_END = NEWS_F_END
+	NEW_F_COUNT = F_COUNT
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	IF (NEW_NEWS_F_END.GT.NEWS_F_END) THEN
+	   CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,F_NEWEST_BTIM)
+	   F_NBULL = NEW_NEWS_F_END
+	   NEWS_F_END = NEW_NEWS_F_END
+	   F_COUNT = NEW_F_COUNT
+	END IF
+
+	IF (F_START.EQ.0.AND.F_NBULL.GT.0) F_START = 1
+
+	CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),%DESCR(NEWEST_EXBTIM))
+	IF (COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).LT.0)
+     &		NEWS_F_EXPIRED_DATE = NEWS_EX_BTIM_KEY
+
+	CALL REWRITE_FOLDER_FILE(IER)
+
+	CALL CLOSE_BULLNEWS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SEND_POST
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /ALT_FOUND/ ALT_FOUND
+	CHARACTER*128 ALT_FOUND
+
+	CHARACTER FILE*132
+
+	C = 0
+
+	IF (.NOT.NEWS_LOGIN()) RETURN
+	DO WHILE (LIB$FIND_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &			//'*.POST',FILE,C))
+50	   IF (.NOT.NEWS_WRITE('POST')) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:3).NE.'340') RETURN
+
+	   OPEN (UNIT=3,FILE=FILE,IOSTAT=IER,STATUS='OLD')
+	   DO WHILE (IER.EQ.0)
+	      READ (3,'(Q,A)',IOSTAT=IER) I,INPUT
+	      IF (IER.EQ.0) THEN
+		 IF (INPUT(:5).EQ.'From:') BULL_PARAMETER = INPUT(7:)
+		 IF (.NOT.NEWS_WRITE(INPUT(:I))) GO TO 100
+	      END IF
+	   END DO
+	   IF (INPUT.NE.'.') THEN
+	      IF (.NOT.NEWS_WRITE('.')) GO TO 100
+	   END IF
+	   IF (.NOT.NEWS_READ()) GO TO 100
+	   IF (BUFFER(:3).EQ.'441'.AND..NOT.ALT_SET()) THEN
+	      REWIND (UNIT=3)
+	      IER = 0
+	      DO WHILE (IER.EQ.0)
+	         READ (3,'(Q,A)',IOSTAT=IER) I,INPUT
+	         IF (IER.EQ.0.AND.INPUT(:12).EQ.'Newsgroups: ') THEN 
+		    CLOSE (UNIT=3)
+		    IF (TEST_ALT(INPUT(13:))) THEN
+			CALL SET_ALT(ALT_FOUND)
+			GOTO 50
+	            END IF
+	            IER = 2
+	         END IF
+	      END DO
+	      CLOSE (UNIT=3)
+	   END IF
+	   IF (BUFFER(:3).NE.'240') THEN
+	      CLOSE (UNIT=3)
+	      CALL SENDMAIL(FILE,BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+     &			,'ERROR: Posting rejected: '//BUFFER(SB:EB),IER)
+	      OPEN (UNIT=3,FILE=FILE,IOSTAT=IER,STATUS='OLD')
+	   END IF
+	   CLOSE (UNIT=3,STATUS='DELETE')
+	   IF (ALT_SET()) CALL UNSET_ALT
+	END DO
+
+100	CLOSE (UNIT=3)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_UNAME(UNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($MAILDEF)'
+
+	CHARACTER*(*) UNAME
+
+	CALL DISABLE_PRIVS
+
+	C = 0
+
+	STATUS = MAIL$USER_BEGIN(C,0,0)
+	IF (.NOT.STATUS) GO TO 100
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(LEN(UNAME),MAIL$_USER_PERSONAL_NAME,
+     &				%LOC(UNAME))
+	CALL END_ITMLST(GET_USER_ITMLST)
+
+	STATUS = MAIL$USER_GET_INFO(C,0,%VAL(GET_USER_ITMLST))
+	IF (.NOT.STATUS) GO TO 100
+
+	STATUS = MAIL$USER_END(C,0,0)
+	IF (.NOT.STATUS) GO TO 100
+
+100	CALL ENABLE_PRIVS
+
+	IF (UNAME.EQ.'()') THEN
+	   UNAME = ' '
+	ELSE IF (TRIM(UNAME).GT.0) THEN
+	   UNAME = ' ('//UNAME(:TRIM(UNAME))//')'
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE RECOUNT
+C
+C  SUBROUTINE RECOUNT
+C
+C  FUNCTION:
+C
+C  Fixes the message count of stored news groups.  This may become wrong
+C  if old copies of some of the database files are used with newer versions.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLFIL/ BULLFIL
+
+	COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+	CHARACTER*80 BULLNEWSDIR_FILE
+
+	FOLDER_NUMBER = 1000
+
+	FOLDER_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY)-1)//'.]'
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1)
+	END DO
+
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLNEWS
+	   RETURN
+	END IF
+
+	REMOTE_SET = 4
+
+	DO WHILE (IER.EQ.0)
+
+	   DO WHILE (REC_LOCK(IER))
+	      READ (7,IOSTAT=IER) NEWS_FOLDER_COM
+	   END DO
+
+	   IF (BTEST(NEWS_F_FLAG,8).AND.IER.EQ.0) THEN
+	      CALL NEWS_TO_FOLDER
+
+	      CALL OPEN_BULLDIR_SHARED
+
+	      NUM = F_START
+	      F_COUNT = 0
+
+	      IF (F_START.GT.0) THEN
+		 CALL READDIR(NUM,IER)
+		 NEXT = .TRUE.
+		 F_START = NUM
+		 DO WHILE (NUM+1.EQ.IER)
+		    F_COUNT = F_COUNT + 1
+		    NUM = NUM + 1
+		    IF (NUM.LE.F_NBULL) CALL READDIR(NUM,IER)
+		 END DO
+		 NEXT = .FALSE.
+
+		 F_NBULL = NUM - 1
+	      END IF
+
+	      CALL CLOSE_BULLDIR
+
+	      CALL REWRITE_FOLDER_FILE(IER)
+	   END IF
+	END DO
+
+	CALL DELLNM('BULL_NEWS_RECOUNT')
+
+	CALL CLOSE_BULLNEWS
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELLNM(LOG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PSLDEF)'
+
+	CHARACTER*(*) LOG
+
+	CALL SYS$DELLNM('LNM$SYSTEM',LOG,PSL$C_SUPER)
+
+	RETURN
+	END
+
+
+	SUBROUTINE DELLNM_USER(LOG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PSLDEF)'
+
+	CHARACTER*(*) LOG
+
+	CALL SYS$DELLNM('LNM$PROCESS',LOG,PSL$C_USER)
+
+	RETURN
+	END
+
+
+	SUBROUTINE NEWNEWS(SINCE_BTIM,FOUND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /XHDR/ XHDR
+	LOGICAL XHDR /.FALSE./
+
+	COMMON /POINT/ BULL_POINT
+
+	CHARACTER*8 NUMBER,NUMBER1
+
+	DIMENSION SINCE_BTIM(2)
+
+	START = F_START
+	END = F_NBULL
+
+	FOUND = 0
+
+	IF (REMOTE_SET.EQ.3.AND.XHDR) THEN
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.OTS$CVT_L_TI(END,NUMBER1,,,)) RETURN
+	   DO WHILE (NUMBER1(1:1).EQ.' ')
+	      NUMBER1 = NUMBER1(2:)
+	   END DO
+	   IF (.NOT.NEWS_WRITE('XHDR DATE '//NUMBER//'-'//NUMBER1))
+     &							     RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).EQ.'22') THEN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      DO WHILE (BUFFER(SB:EB).NE.'.')
+		 IF (FOUND.EQ.0) THEN
+		    L = INDEX(BUFFER(SB:EB),' ')
+		    CALL OTS$CVT_TI_L(BUFFER(SB:SB+L-2),IER,,%VAL(1))
+		    CALL NEWS_TIME(BUFFER(SB+L:EB),MSG_BTIM)
+		    CALL CONVERT_FROM_GMT(MSG_BTIM)
+		    IF (COMPARE_BTIM(SINCE_BTIM,MSG_BTIM).LT.0)
+     &			     FOUND = IER
+		 END IF
+		 IF (.NOT.NEWS_READ()) RETURN
+	      END DO
+	      IF (FOUND.NE.0) THEN
+		 IF (.NOT.OTS$CVT_L_TI(FOUND,NUMBER,,,)) RETURN
+		 IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+	      END IF
+	   END IF
+	ELSE IF (REMOTE_SET.EQ.3.AND..NOT.XHDR) THEN
+	   IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+	   IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+	   IF (.NOT.NEWS_READ()) RETURN
+	   IF (BUFFER(:2).NE.'22') THEN
+	      IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IF (.NOT.OTS$CVT_TI_L(BUFFER(SB+4:
+     &		  INDEX(BUFFER(SB+4:),' ')+SB+2),I,,%VAL(1))) RETURN
+	      IF (BUFFER(:2).NE.'22'.OR.I.LT.START) THEN
+		 BUFFER(:3) = '500'
+		 DO WHILE (START.LE.F_NBULL.AND.BUFFER(:2).NE.'22')
+		    START = START + 1
+		    IF (.NOT.OTS$CVT_L_TI(START,NUMBER,,,)) RETURN
+		    IF (.NOT.NEWS_WRITE('HEAD '//NUMBER)) RETURN
+		    IF (.NOT.NEWS_READ()) RETURN
+		 END DO
+		 IF (BUFFER(:2).NE.'22') THEN
+		    IER = 0
+		    END = START - 1
+		    RETURN
+		 END IF
+	      END IF
+	      IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &			INDEX(BUFFER(SB+4:),' ')+SB+2),START,,%VAL(1))
+	      END = START + NUMDIR - 1
+	   END IF
+	   IER = 0
+	   I = START
+	   DO WHILE (IER.EQ.0.AND.I.LE.END.AND.FOUND.EQ.0)
+	      IER = OTS$CVT_TI_L(BUFFER(SB+4:
+     &		     INDEX(BUFFER(SB+4:),' ')+SB+2),MSG_NUM,,%VAL(1))
+	      CALL NEWS_HEADER(IER)
+	      IF (IER.NE.0) RETURN
+	      CALL CONVERT_FROM_GMT(MSG_BTIM)
+	      IF (COMPARE_BTIM(SINCE_BTIM,MSG_BTIM).LT.0) FOUND = MSG_NUM
+	      I = I + 1
+	      IF (REMOTE_SET.EQ.3.AND.I.LE.END.AND.FOUND.EQ.0) THEN
+		 IER = 2
+		 IF (.NOT.NEWS_WRITE('NEXT')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IF (BUFFER(:3).NE.'223') THEN
+		    END = I - 1
+		    IER = 0
+		    RETURN
+		 END IF
+		 IF (.NOT.NEWS_WRITE('HEAD')) RETURN
+		 IF (.NOT.NEWS_READ()) RETURN
+		 IER = 0
+	      END IF
+	   END DO
+	   IF (FOUND.EQ.0) THEN
+	      IF (.NOT.OTS$CVT_L_TI(BULL_POINT,NUMBER,,,)) RETURN
+	      IF (.NOT.NEWS_WRITE('STAT '//NUMBER)) RETURN
+	      IF (.NOT.NEWS_READ()) RETURN
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST_ALT(FOLDER1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /ALT_FOUND/ ALT_FOUND
+	CHARACTER*128 ALT_FOUND
+
+        CHARACTER*(*) FOLDER1
+
+	TEST_ALT = .FALSE.
+
+	OPEN (UNIT=3,FILE=FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &	      'BULL_ALT_NEWS.LIS',IOSTAT=IER,STATUS='OLD',READONLY)
+	
+	IF (IER.NE.0) RETURN
+
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(A)',IOSTAT=IER) ALT_FOUND
+	   IF (STREQ(ALT_FOUND(:INDEX(ALT_FOUND,':')-1),
+     &	      FOLDER1(:TRIM(FOLDER1)))) THEN
+	      ALT_FOUND = ALT_FOUND(INDEX(ALT_FOUND,':')+1:)
+	      CLOSE (UNIT=3)
+	      TEST_ALT = .TRUE.
+	      RETURN
+	   END IF
+	END DO
+
+	CLOSE (UNIT=3)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION SET_ALT(NEWALT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) NEWALT
+
+	COMMON /ALT/ ALT,SETALT
+	CHARACTER*64 ALT
+	LOGICAL SETALT
+	DATA SETALT/.FALSE./
+
+	SET_ALT = .FALSE.
+
+	IF (SETALT) THEN
+	   IF (NEWALT.EQ.ALT) THEN
+	      SET_ALT = .TRUE.
+	      RETURN
+	   ELSE
+	      CALL UNSET_ALT
+	   END IF
+	END IF
+
+	CALL NEWS_LOGOUT
+
+	CALL CRELNM('BULL_NEWS_SERVER',NEWALT(:TRIM(NEWALT)))
+
+	IF (NEWS_LOGIN()) THEN
+	   SET_ALT = .TRUE.
+	   SETALT = .TRUE.
+	   ALT = NEWALT
+	ELSE
+	   CALL DELLNM_USER('BULL_NEWS_SERVER')
+	   SETALT = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+        SUBROUTINE UNSET_ALT
+
+        IMPLICIT INTEGER (A-Z)
+
+        COMMON /ALT/ ALT,SETALT
+        CHARACTER*64 ALT
+	LOGICAL SETALT
+
+	CALL DELLNM_USER('BULL_NEWS_SERVER')
+
+	CALL NEWS_LOGOUT
+
+	SETALT = .FALSE.
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION ALT_SET()
+
+        COMMON /ALT/ ALT,SETALT
+        CHARACTER*64 ALT
+	LOGICAL SETALT
+
+	ALT_SET = SETALT
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_NEW_NEWS_ENTRY(FLEN,LOCAL_UPDATE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	DIMENSION EXPIRED(2)
+
+	CALL STR$UPCASE(NEWS_FOLDER,NEWS_FOLDER1)
+	IER2 = 1
+	I = FLEN
+	NEWS_F1_COUNT = NEWS_F_COUNT
+	DO WHILE (IER2.NE.0.AND.I.GT.1)
+	   IF (NEWS_FOLDER(I:I).EQ.'.') THEN
+	      NEWS_FOLDER = NEWS_FOLDER(:I)
+	      DO WHILE (REC_LOCK(IER))
+	         READ (7,KEY=NEWS_FOLDER,
+     &	               KEYID=0,IOSTAT=IER2) NEWS_FOLDER_COM
+	      END DO
+	   END IF
+	   IF (IER2.NE.0) I = I - 1
+	END DO
+	NEWS_F_COUNT = NEWS_F1_COUNT
+	IER = 0
+	DO WHILE (IER.EQ.0.AND.IER1.EQ.0)
+	   DO WHILE (REC_LOCK(IER))
+	      READ (7,KEY=NEWS_F_COUNT,KEYID=1,IOSTAT=IER)
+	   END DO
+	   IF (IER.EQ.0) NEWS_F_COUNT = NEWS_F_COUNT + 1
+	END DO
+	NEWS_FOLDER1_NUMBER = NEWS_F_COUNT
+	IF (IER2.EQ.0) THEN
+	   NEWS_F1_FLAG = NEWS_F_FLAG
+	   NEWS_F1_FLAG = IBCLR(NEWS_F1_FLAG,10)
+	   IF (I.NE.INDEX(NEWS_FOLDER1,'.')) THEN
+	      NEWS_F1_EXPIRE = NEWS_F_EXPIRE
+	      NEWS_F1_EXPIRE_LIMIT = NEWS_F_EXPIRE_LIMIT
+	   END IF
+	ELSE
+	   NEWS_F1_FLAG = NEWS_FLAG_DEFAULT
+	   NEWS_F1_EXPIRE = 0
+	   NEWS_F1_EXPIRE_LIMIT = 0
+	END IF
+	CALL GET_MSGKEY(NEWS_F1_NEWEST_BTIM,NEWS_F1_CREATED_DATE)
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',EXPIRED)
+	CALL GET_MSGKEY(EXPIRED,NEWS_F1_EXPIRED_DATE)
+	NEWS_F1_COUNT = MAX(0,NEWS_F1_NBULL - NEWS_F1_START + 1)
+	IF (BTEST(NEWS_F1_FLAG,8)) THEN
+	   NEWS_F1_COUNT = 0
+	   NEWS_F1_START = 0
+	   NEWS_F1_NBULL = 0
+	   NEWS_F1_FIRST = 0
+	   NEWS_F1_LAST = 0
+	END IF
+
+	WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	IF (IER.EQ.0) THEN
+	  NEWS_F_COUNT = NEWS_F_COUNT + 1
+	   IF (BTEST(NEWS_F1_FLAG,8).AND.
+     &	     .NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+	       CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,
+     &	     	%DESCR(NEWS_FOLDER1_NUMBER))
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE UPDATE_NEWS_ENTRY(SPECIAL,LOCAL_UPDATE,FLEN,SP)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BUFFER/ BUFFER,SB,EB
+	CHARACTER BUFFER*1280
+
+	IF (BTEST(NEWS_F1_FLAG,8).AND.
+     &			.NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+	   IF (NEWS_F1_LAST.NE.NEWS_F1_NBULL.AND..NOT.SPECIAL.AND.
+     &	       NEWS_F1_START.LE.NEWS_F1_NBULL) THEN
+	      IF (NEWS_F1_FIRST.GT.NEWS_F1_START.AND.
+     &		  NEWS_F1_FIRST.GT.NEWS_F1_NBULL) THEN
+		 NEWS_F1_LAST = 0
+		 NEWS_F1_START = F1_START
+		 NEWS_F1_NBULL = F1_NBULL
+		 REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	      END IF
+	      IF (NEWS_F1_LAST.LT.NEWS_F1_NBULL) THEN
+		 CALL WRITE_QUEUE(%VAL(LOCAL_UPDATE),LOCAL_UPDATE,
+     &					%DESCR(NEWS_FOLDER1_NUMBER))
+	      END IF
+	   END IF
+	ELSE IF (.NOT.BTEST(NEWS_F1_FLAG,9)) THEN
+	   UPDATE = .FALSE.
+	   IF (SP.GT.0) THEN 
+	      IF (FLEN.GT.44) THEN
+	         IF (NEWS_FOLDER1_DESCRIP.NE.
+     &	             BUFFER(SB+44:FLEN+SB-1)//BUFFER(SP:EB)) THEN
+		    NEWS_FOLDER1_DESCRIP =
+     &			BUFFER(SB+44:FLEN+SB-1)//BUFFER(SP:EB)
+		    UPDATE = .TRUE.
+	         END IF
+	      ELSE IF (NEWS_FOLDER1_DESCRIP.NE.BUFFER(SP:EB)) THEN
+	         NEWS_FOLDER1_DESCRIP = BUFFER(SP:EB)
+	         UPDATE = .TRUE.
+	      END IF
+	   ELSE
+	      UPDATE = .TRUE.
+	   END IF
+	   IF (SPECIAL) THEN
+	      IF (UPDATE) THEN
+		 NEWS_F1_START = F1_START
+		 NEWS_F1_NBULL = F1_NBULL
+	      END IF
+	   ELSE IF (.NOT.UPDATE) THEN
+	      UPDATE = F1_START.LT.NEWS_F1_START.OR.
+     &		       F1_NBULL.NE.NEWS_F1_NBULL
+	   END IF
+	   IF (UPDATE) REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	END IF
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin11.for b/decus/vmslt98a/bulletin/bulletin11.for
new file mode 100755
index 0000000000000000000000000000000000000000..2805f71651d2a2f13fe0c23ef0b8dfec2fff51db
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin11.for
@@ -0,0 +1,3549 @@
+C
+C  BULLETIN11.FOR, Version 2/20/98
+C  Purpose: Bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE RESET
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.GE.3) THEN
+	   IF (NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) THEN
+	      WRITE (6,'('' ERROR: NEWS group is not subscribed.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('CURRENT')) THEN
+	   MESSAGE_NUMBER = BULL_POINT
+	ELSE IF (.NOT.CLI$GET_VALUE('NUMBER',BULL_PARAMETER,LEN_P)) THEN
+	   MESSAGE_NUMBER = NBULL
+	ELSE
+	   CALL GET_2_VALS(BULL_PARAMETER,LEN_P,MESSAGE_NUMBER,EBULL,IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'(A)') 
+     &	        ' ERROR: Specified message number has incorrect format.'
+	      RETURN
+	   END IF
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(MESSAGE_NUMBER,IER)
+	IF (IER.EQ.MESSAGE_NUMBER+1		! Was message found?
+     &	          .OR.REMOTE_SET.GE.3) THEN	! Ignore if news
+	   IF (REMOTE_SET.LT.3) THEN
+	      CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),MSG_BTIM)
+	   ELSE
+	      I = NEWS_FIND_SUBSCRIBE()
+	      LAST_NEWS_READ(2,I) = MESSAGE_NUMBER
+	      LAST_NEWS_READ2(2,I) = MIN(8191,F_NBULL-MESSAGE_NUMBER)
+     &			.OR.(LAST_NEWS_READ2(2,I).AND.'C000'X)
+	   END IF
+	ELSE
+	   WRITE(6,1030) MESSAGE_NUMBER
+	END IF
+
+100	IF (REMOTE_SET.GE.3) CALL READDIR(BULL_POINT,IER)
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+
+1010	FORMAT(' ERROR: You have not read any message.')
+1030	FORMAT(' ERROR: Message was not found: ',I)
+
+	END
+
+
+
+	SUBROUTINE TAG(ADD_OR_DEL,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+	DATA BULL_TAG /.FALSE./,READ_TAG /.FALSE./,BULL_NEWS_TAG /.FALSE./
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	CHARACTER*12 TAG_KEY
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	IF ((.NOT.BULL_TAG.AND.REMOTE_SET.LT.3)
+     &	    .OR.(.NOT.BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)) THEN
+	   CALL OPEN_NEW_TAG(IER)
+	   IF (.NOT.IER) RETURN
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+	   IF (NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) THEN
+	      WRITE (6,'('' ERROR: NEWS group is not subscribed.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	IF (ADD_OR_DEL.AND.
+     &		INCMD(:4).NE.'MARK'.AND.INCMD(:4).NE.'SEEN') THEN
+	   CALL ADD_TAG(IER,TAG_TYPE)
+	   RETURN
+	END IF
+
+	IF (INCMD(:4).EQ.'SEEN') THEN
+	   IF (CLI$PRESENT('READ').EQ.%LOC(CLI$_NEGATED)) THEN
+	      READ (13,KEYEQ=TAG_KEY(0,BULLDIR_HEADER,1),
+     &		    IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE (UNIT=13)
+	      BULL_TAG = IBCLR(BULL_TAG,1)
+	      RETURN
+	   END IF
+	END IF
+
+	IF (.NOT.CLI$PRESENT('NUMBER')) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! No.  Have we just read a bulletin?
+	      WRITE(6,1010)		! No, then error.
+	      RETURN
+	   ELSE IF (ADD_OR_DEL) THEN
+	      CALL ADD_TAG(IER,TAG_TYPE)
+	   ELSE
+	      CALL DEL_TAG(IER,TAG_TYPE)
+	      IF (IER.NE.0) THEN
+		 IF (TAG_TYPE.EQ.1) THEN
+		    WRITE (6,'('' ERROR: Message was not marked.'')')
+		 ELSE
+		    WRITE (6,'('' ERROR: Message was not seen.'')')
+		 END IF
+	      END IF
+	   END IF
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLDIR_SHARED
+
+	LAST = 0
+
+	DO WHILE (CLI$GET_VALUE('NUMBER',BULL_PARAMETER,LEN_P)
+     &	    .NE.%LOC(CLI$_ABSENT)) 		! Get the specified messages
+
+	   CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER)
+
+	   IF (SBULL.LE.0.OR.IER.NE.0.OR.SBULL.GT.F_NBULL) THEN
+	      WRITE (6,'(A)') 
+     &	        ' ERROR: Specified message number has incorrect format.'
+	      GO TO 100
+	   END IF
+
+	   DO MESSAGE_NUMBER = SBULL,MIN(EBULL,F_NBULL)
+
+	      CALL READDIR(MESSAGE_NUMBER,IER)
+	      IF (IER.NE.MESSAGE_NUMBER+1	! Was message found?
+     &	          .AND.REMOTE_SET.LT.3) THEN	! Ignore if news
+	         WRITE(6,1030) MESSAGE_NUMBER	! No
+		 GO TO 100
+	      ELSE IF (ADD_OR_DEL) THEN
+	         CALL ADD_TAG(IER,TAG_TYPE)
+	         IF (TAG_TYPE.EQ.2.AND.MESSAGE_NUMBER.GT.LAST) THEN
+		    IF (REMOTE_SET.LT.3) THEN
+	   	       DIFF = COMPARE_BTIM(MSG_BTIM,
+     &				LAST_READ_BTIM(1,FOLDER_NUMBER+1))
+		       IF (DIFF.GT.0) CALL COPY2(LAST_READ_BTIM
+     &		          	(1,FOLDER_NUMBER+1),MSG_BTIM)
+		    ELSE
+		       CALL NEWS_UPDATE_NEWEST_MESSAGE(MESSAGE_NUMBER)
+	            END IF
+	            LAST = MESSAGE_NUMBER
+	         END IF
+	      ELSE
+	         CALL DEL_TAG(IER,TAG_TYPE)
+	      END IF
+	   END DO
+	END DO
+
+100	IF (REMOTE_SET.GE.3) CALL READDIR(BULL_POINT,IER)
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+
+1010	FORMAT(' ERROR: You have not read any message.')
+1030	FORMAT(' ERROR: Message was not found: ',I)
+
+	END
+
+
+
+	SUBROUTINE ADD_TAG(IER,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER*12 TAG_KEY
+
+	IF (REMOTE_SET.LT.3) THEN
+	   IF (TAG_TYPE.EQ.2.AND..NOT.BTEST(BULL_TAG,1)) THEN ! No SEEN tags
+	      WRITE (13,IOSTAT=IER) TAG_KEY(0,BULLDIR_HEADER,1)
+	      BULL_TAG = IBSET(BULL_TAG,1)
+	   END IF
+	   WRITE (13,IOSTAT=IER) TAG_KEY(FOLDER_NUMBER,MSG_KEY,TAG_TYPE)
+	ELSE
+	   CALL ADD_NEWS_TAG(IER,TAG_TYPE)
+	   RETURN
+	END IF
+
+	IF (IER.NE.FOR$IOS_INCKEYCHG.AND.IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Unable to mark message.'')')
+	   CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	ELSE
+	   IER = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_FIRST_NEWS_TAG(IER,MESSAGE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+        COMMON /NEXT/ NEXT
+
+	IER = 36
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	DO J=1,2
+	   IF (BTEST(READ_TAG,J)) I = J
+	END DO
+
+	IF (NEWS_TAG(3,I,SUBNUM).EQ.0) RETURN
+
+	INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	CLOSE_IT = .NOT.CLOSE_IT
+	IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+
+	OLD_NEXT = NEXT
+
+	NEXT = .FALSE.
+	J = F_START - 1
+	IER1 = J
+	DO WHILE (J.LE.F_NBULL.AND.J+1.NE.IER1)
+	   J = J + 1
+	   CALL READDIR(J,IER1)
+	END DO
+
+	IF (J+1.NE.IER1) THEN
+	   NEXT = OLD_NEXT
+	   IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+	   RETURN
+	END IF
+
+	NEXT = .TRUE.
+
+	DO MESSNUM = NEWS_TAG(1,I,SUBNUM),NEWS_TAG(2,I,SUBNUM)
+	   TEST = TEST_TAG(MESSNUM,%VAL(NEWS_TAG(3,I,SUBNUM)),
+     &			NEWS_TAG(1,I,SUBNUM))
+	   IF (BTEST(READ_TAG,3)) TEST = .NOT.TEST
+	   IF (TEST) THEN
+	      HEADER = .TRUE.
+	      CALL GET_NEXT_NEWS_TAG(IER,MESSNUM,HEADER,I,SUBNUM)
+	      IF (IER.EQ.0) MESSAGE = MESSNUM
+	      NEXT = OLD_NEXT
+	      IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+	      RETURN
+	   END IF
+	END DO
+
+	NEXT = OLD_NEXT
+	IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+
+	RETURN
+
+	ENTRY GET_THIS_NEWS_TAG(IER,MESSAGE,TAG_TYPE)
+
+	IER = 36
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	TAG_TYPE = 0
+
+	DO I=1,2
+	   IF ((BTEST(READ_TAG,I).OR.BTEST(READ_TAG,3))
+     &	    .AND.(NEWS_TAG(3,I,SUBNUM).GT.0).AND.
+     &	    (MSG_NUM.LE.NEWS_TAG(2,I,SUBNUM))) THEN
+	      TEST = TEST_TAG(MSG_NUM,
+     &		%VAL(NEWS_TAG(3,I,SUBNUM)),NEWS_TAG(1,I,SUBNUM))
+	      IF (TEST) THEN
+	         IER = 0
+	         TAG_TYPE = IBSET(TAG_TYPE,I)
+	      END IF
+	   END IF
+	END DO
+
+	IF (BTEST(READ_TAG,3)) THEN
+	   IF ((.NOT.BTEST(TAG_TYPE,2).OR..NOT.BTEST(READ_TAG,2)).AND.
+     &	       (.NOT.BTEST(TAG_TYPE,1).OR..NOT.BTEST(READ_TAG,1))) THEN
+	      IER = 0
+	   ELSE
+	      IER = 36
+	   END IF
+	END IF
+
+	RETURN
+
+	ENTRY GET_THIS_OR_NEXT_NEWS_TAG(NUM,IER,MESSAGE,TAG_TYPE)
+
+	IER = 36
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	HEADER = .FALSE.
+
+	TAG_TYPE = 0
+
+	DO WHILE (IER.NE.0)
+	   I = 0
+	   DO J=1,2
+	      IF (NEWS_TAG(3,J,SUBNUM).GT.0.AND.BTEST(READ_TAG,J)) THEN
+		 IER = 36
+		 MNUM = MAX(NEWS_TAG(1,J,SUBNUM),NUM)
+	   	 DO WHILE (IER.NE.0.AND.MNUM.LE.NEWS_TAG(2,J,SUBNUM))
+	     	    TEST = TEST_TAG(MNUM,%VAL(NEWS_TAG(3,J,SUBNUM)),
+     &		  	NEWS_TAG(1,J,SUBNUM))
+		    IF (BTEST(READ_TAG,3)) TEST = .NOT.TEST
+		    IF (TEST) THEN
+		       IER = 0
+		    ELSE
+		       MNUM = MNUM + 1
+		    END IF
+		 END DO
+		 IF (IER.EQ.0) THEN
+		    IF (J.EQ.1) THEN
+		       MESSAGE = MNUM
+		       I = 1
+		    ELSE IF (I.EQ.0.OR.MESSAGE.GT.MNUM) THEN
+		       MESSAGE = MNUM
+		       I = 2
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (I.EQ.0) RETURN
+	   CALL GET_NEXT_NEWS_TAG(IER,MESSAGE,HEADER,I,SUBNUM)
+	   IF (IER.EQ.0) THEN
+	      IF (.NOT.BTEST(READ_TAG,3)) TAG_TYPE = IBSET(TAG_TYPE,I)
+	      IF (NEWS_TAG(3,3-I,SUBNUM).GT.0.AND.
+     &		  MESSAGE.LE.NEWS_TAG(2,3-I,SUBNUM)) THEN
+		 IF (TEST_TAG(MESSAGE,%VAL(NEWS_TAG(3,3-I,SUBNUM)),
+     &		  	NEWS_TAG(1,3-I,SUBNUM))) THEN
+		    TAG_TYPE = IBSET(TAG_TYPE,3-I)
+                 END IF
+	      END IF
+	      RETURN
+	   ELSE IF (.NOT.BTEST(READ_TAG,3-I)) THEN
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NEXT_NEWS_TAG(IER,MESSNUM,HEADER,J,SUBNUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+        COMMON /NEXT/ NEXT
+
+	INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	CLOSE_IT = .NOT.CLOSE_IT
+	IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+
+	IER = 36
+
+	OLD_NEXT = NEXT
+
+	DO WHILE (MESSNUM.LE.NEWS_TAG(2,J,SUBNUM).AND.IER.NE.0)
+	   I = MAX(NEWS_TAG(1,J,SUBNUM),MESSNUM)
+	   DO WHILE (IER.NE.0.AND.I.LE.NEWS_TAG(2,J,SUBNUM))
+	      TEST = TEST_TAG(I,%VAL(NEWS_TAG(3,J,SUBNUM)),
+     &		  NEWS_TAG(1,J,SUBNUM))
+	      IF (BTEST(READ_TAG,3)) TEST = .NOT.TEST
+	      IF (TEST) THEN
+	         IER = 0
+	         MESSNUM = I
+	      ELSE
+		 I = I + 1
+	      END IF
+	   END DO
+	   IF (IER.EQ.0) THEN
+	      SAVE_MESSNUM = MESSNUM
+	      NEXT = .FALSE.
+	      CALL READDIR(MESSNUM,IER1)
+	      IF (IER1.NE.MESSNUM+1) THEN
+	         NEXT = .TRUE.
+	         CALL READDIR(MESSNUM,IER1)
+	      END IF
+	      IF (IER1.NE.MESSNUM+1) THEN
+		 IER = 36
+	         IF (.NOT.BTEST(READ_TAG,3)) THEN
+		    CALL DEL_NEWS_TAG(J,MESSNUM,SUBNUM)
+		 ELSE
+		    NEXT = OLD_NEXT
+		    IF (CLOSE_IT) CALL CLOSE_BULLDIR
+		    RETURN
+		 END IF
+		 IF (BTEST(READ_TAG,1).AND.BTEST(READ_TAG,2)) RETURN
+	      ELSE IF (MESSNUM.NE.SAVE_MESSNUM) THEN
+		 IER = 36
+	         IF (.NOT.BTEST(READ_TAG,3)) THEN
+		    CALL DEL_NEWS_TAG(J,SAVE_MESSNUM,SUBNUM)
+		 END IF
+	      END IF
+	   ELSE
+	      MESSNUM = NEWS_TAG(2,J,SUBNUM) + 1
+	   END IF
+	END DO
+
+	IF (IER.EQ.0.AND.HEADER) THEN
+	   MESSNUM = MESSNUM - 1
+	   MSG_NUM = MESSNUM
+	END IF
+
+	NEXT = OLD_NEXT
+
+	IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE ADD_NEWS_TAG(IER,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	IF (.NOT.BULL_NEWS_TAG) RETURN
+
+	IER = 0
+
+	SUBNUM = NEWS_FIND_SUBSCRIBE()
+	IF (SUBNUM.GT.FOLDER_MAX-1) RETURN
+
+	IF (NEWS_TAG(1,TAG_TYPE,SUBNUM).GT.F_START) THEN
+	   CALL LIB$FREE_VM((NEWS_TAG(2,TAG_TYPE,SUBNUM)-
+     &			  NEWS_TAG(1,TAG_TYPE,SUBNUM))/8+1,
+     &			  NEWS_TAG(3,TAG_TYPE,SUBNUM))
+	   NEWS_TAG(2,TAG_TYPE,SUBNUM) = F_NBULL
+	   NEWS_TAG(3,TAG_TYPE,SUBNUM) = 0
+	END IF
+
+	IF (NEWS_TAG(3,TAG_TYPE,SUBNUM).EQ.0.AND.F_NBULL.GE.F_START) THEN
+	   NEWS_TAG(1,TAG_TYPE,SUBNUM) = F_START
+	   NEWS_TAG(2,TAG_TYPE,SUBNUM) = F_NBULL
+	   CALL LIB$GET_VM((F_NBULL-F_START)/8+1,
+     &			   NEWS_TAG(3,TAG_TYPE,SUBNUM))
+	   CALL ZERO_VM((F_NBULL-F_START)/8+1,
+     &			%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)))
+	ELSE IF (F_NBULL.GT.NEWS_TAG(2,TAG_TYPE,SUBNUM)) THEN
+	   DO I=1,2
+	      IF (NEWS_TAG(1,I,SUBNUM).GT.0) THEN
+	         CALL LIB$GET_VM((F_NBULL-NEWS_TAG(1,I,SUBNUM))/8+1,TEMP)
+	         CALL ZERO_VM((F_NBULL-NEWS_TAG(1,I,SUBNUM))/8+1,
+     &			%VAL(TEMP))
+	         CALL LIB$MOVC3((NEWS_TAG(2,I,SUBNUM)-
+     &			  NEWS_TAG(1,I,SUBNUM))/8+1,
+     &			  %VAL(NEWS_TAG(3,I,SUBNUM)),%VAL(TEMP))
+	         CALL LIB$FREE_VM((NEWS_TAG(2,I,SUBNUM)-
+     &			  NEWS_TAG(1,I,SUBNUM))/8+1,
+     &			  NEWS_TAG(3,I,SUBNUM))
+	         NEWS_TAG(2,I,SUBNUM) = F_NBULL
+	         NEWS_TAG(3,I,SUBNUM) = TEMP
+	      END IF
+	   END DO
+	END IF
+
+	CALL SET_TAG(MSG_NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		     NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	NEWS_TAG(4,TAG_TYPE,SUBNUM) = 1
+		 
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_TAG(NUM,TAGS,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION TAGS(1)
+
+	I = (NUM-START)/32
+	J = NUM - START - I*32
+
+	TAGS(I+1) = IBSET(TAGS(I+1),J)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CLR_TAG(NUM,TAGS,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION TAGS(1)
+
+	I = (NUM-START)/32
+	J = NUM - START - I*32
+
+	TAGS(I+1) = IBCLR(TAGS(I+1),J)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST_TAG(NUM,TAGS,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION TAGS(1)
+
+	I = (NUM-START)/32
+	J = NUM - START - I*32
+
+	TEST_TAG = BTEST(TAGS(I+1),J)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DEL_TAG(IER,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*12 TAG_KEY
+
+	IER = 0
+
+	IF (REMOTE_SET.GE.3) THEN
+	   SUBNUM = NEWS_FIND_SUBSCRIBE()
+	   CALL DEL_NEWS_TAG(TAG_TYPE,MSG_NUM,SUBNUM)
+	   RETURN
+	END IF
+
+	DO WHILE (REC_LOCK(IER1))
+	   READ (13,KEYEQ=TAG_KEY(FOLDER_NUMBER,MSG_KEY,TAG_TYPE),
+     &		 IOSTAT=IER1)
+	END DO
+	IF (IER1.NE.0) RETURN
+
+	DELETE (UNIT=13,IOSTAT=IER1)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DEL_NEWS_TAG(TAG_TYPE,MSG_NUM,SUBNUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	IF (MSG_NUM.LT.NEWS_TAG(1,TAG_TYPE,SUBNUM).OR.
+     &	   MSG_NUM.GT.NEWS_TAG(2,TAG_TYPE,SUBNUM).OR..NOT.TEST_TAG
+     &	    (MSG_NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM))
+     &	    ,NEWS_TAG(1,TAG_TYPE,SUBNUM))) THEN
+	   RETURN
+	ELSE
+	   NEWS_TAG(4,TAG_TYPE,SUBNUM) = 1
+	   CALL CLR_TAG
+     &		(MSG_NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE OPEN_OLD_TAG
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	CHARACTER*12 BULL_MARK_DIR
+	CHARACTER*12 TAG_KEY,INPUT_KEY
+
+	IER = SYS_TRNLNM('BULL_MARK',BULL_PARAMETER)
+	IF (IER) THEN
+	   BULL_MARK_DIR = 'BULL_MARK:'
+	ELSE
+	   BULL_MARK_DIR = 'SYS$LOGIN:'
+	END IF
+
+	NTRIES = 0
+
+	DO WHILE (FILE_LOCK(IER,IER1).AND.NTRIES.LE.30)
+	   OPEN (UNIT=13,FILE=BULL_MARK_DIR//
+     &	     USERNAME(:TRIM(USERNAME))//'.BULLMARK',STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	     ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	     KEY=(1:12:CHARACTER))
+	   NTRIES = NTRIES + 1
+	END DO
+
+	IF (IER.EQ.0) THEN
+	   BULL_TAG = IBSET(BULL_TAG,0)
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (13,KEY=TAG_KEY(0,BULLDIR_HEADER,1),IOSTAT=IER1)
+	   END DO
+	   IF (IER1.EQ.0) BULL_TAG = IBSET(BULL_TAG,1)
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (13,KEYGE=TAG_KEY('FFFF'X,BULLDIR_HEADER,1),IOSTAT=IER1)
+     &		         INPUT_KEY
+	   END DO
+	   CALL LIB$MOVC3(4,%REF(INPUT_KEY),FOLDER1_NUMBER)
+	   IF (IER1.EQ.0.AND.FOLDER1_NUMBER.EQ.'FFFF'X) THEN
+	      MSG_KEY = INPUT_KEY(5:)
+	      CALL SYS$ASCTIM(,DATE,MSG_BTIM,)
+	      IF (COMPARE_DATE(DATE,' ').LT.-30) THEN
+		 DELETE (13)
+	         IER1 = 2
+	      END IF
+	   END IF
+	   IF (IER1.NE.0.OR.FOLDER1_NUMBER.NE.'FFFF'X) THEN
+	      CLOSE (UNIT=13)           
+	      IER1 = 1
+              DO WHILE (IER1)
+	         IER1 = LIB$DELETE_FILE(
+     &			BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))
+     &	            	//'.BULLMARK;-1')
+	      END DO
+	      CALL CONV$PASS_FILES(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK',
+     &	        BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARKTMP')
+	      CALL CONV$PASS_OPTIONS()
+	      CALL CONV$CONVERT()
+	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK;1')
+    	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARKTMP',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.BULLMARK')
+              CALL LIB$DELETE_FILE(BULL_MARK_DIR//
+     &		USERNAME(:TRIM(USERNAME))//'.BULLMARK;-1')
+	      DO WHILE (FILE_LOCK(IER,IER1).AND.NTRIES.LE.30)
+	         OPEN (UNIT=13,FILE=BULL_MARK_DIR//
+     &	    	    USERNAME(:TRIM(USERNAME))//'.BULLMARK',STATUS='OLD',
+     &	    	    ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	    	    ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	    	    KEY=(1:12:CHARACTER))
+	  	 NTRIES = NTRIES + 1
+	      END DO
+	      CALL SYS_BINTIM('-',MSG_BTIM)
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      WRITE (13,IOSTAT=IER) TAG_KEY('FFFF'X,MSG_KEY,1)
+	   ELSE
+	      UNLOCK 13
+	   END IF
+	END IF
+
+	IF (IER.EQ.0.OR.IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	   OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	      USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	      ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	      FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	      KEY=(1:4:INTEGER))
+
+	   IF (IER.EQ.0) THEN
+	      IF (BULL_NEWS_TAG) RETURN
+	      BULL_NEWS_TAG = .TRUE.
+	   ELSE
+	      CALL ERRSNS(IDUMMY,IER1)
+	      IF (IER1.EQ.RMS$_FLK) THEN
+	         BULL_NEWS_TAG = .FALSE.
+	         RETURN
+	      END IF
+	   END IF
+
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (23,KEYEQ=0,IOSTAT=IER1) NEWS_MARK
+	   END DO
+	   IF (IER1.EQ.0) CALL SYS$ASCTIM(,DATE,NEWS_MARK(2),)
+	   IF (IER1.NE.0) THEN
+	      CLOSE (UNIT=23)
+	      OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:4:INTEGER))
+	      IF (IER.EQ.0) THEN
+	      OPEN (UNIT=24,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=128,DISPOSE='DELETE',
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:4:INTEGER))
+	      DO WHILE (IER.EQ.0)
+	         DO WHILE (REC_LOCK(IER))
+		    READ (23,IOSTAT=IER) NEWS_MARK
+	         END DO
+	         IF (IER.EQ.0) THEN
+		    I = NEWS_MARK2(1)
+		    NEWS_MARK2(1) = NEWS_MARK2(2)
+		    NEWS_MARK2(2) = I
+	            WRITE (24,IOSTAT=IER) NEWS_MARK
+	         END IF
+	      END DO
+	      NEWS_MARK(1) = 0
+	      CALL SYS_BINTIM('-',NEWS_MARK(2))
+	      WRITE (24,IOSTAT=IER) NEWS_MARK
+	      CLOSE (UNIT=24,DISPOSE='SAVE')
+	      CLOSE (UNIT=23,DISPOSE='DELETE')
+	      END IF
+	      DO WHILE (FILE_LOCK(IER,IER1))
+	        OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	           USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	           ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	           FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	           KEY=(1:4:INTEGER))
+	      END DO
+	   ELSE IF (COMPARE_DATE(DATE,' ').LT.-30) THEN
+	      CLOSE (UNIT=23)           
+	      IER1 = 1
+              DO WHILE (IER1)
+	         IER1 = LIB$DELETE_FILE(
+     &			BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))
+     &	            	//'.NEWSMARK;-1')
+	      END DO
+	      CALL CONV$PASS_FILES(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK',
+     &	        BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARKTMP')
+	      CALL CONV$PASS_OPTIONS()
+	      CALL CONV$CONVERT()
+	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK;1')
+	      CALL LIB$RENAME_FILE(
+     &		BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARKTMP',
+     &	      	BULL_MARK_DIR//USERNAME(:TRIM(USERNAME))//'.NEWSMARK')
+              CALL LIB$DELETE_FILE(BULL_MARK_DIR//
+     &		USERNAME(:TRIM(USERNAME))//'.NEWSMARK;-1')
+	      DO WHILE (FILE_LOCK(IER,IER1))
+	        OPEN (UNIT=23,FILE=BULL_MARK_DIR//
+     &	           USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='OLD',
+     &	           ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	           FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	           KEY=(1:4:INTEGER))
+	      END DO
+	      DO WHILE (REC_LOCK(IER1))
+	         READ (23,KEYEQ=0,IOSTAT=IER1) NEWS_MARK
+	      END DO
+	      CALL SYS_BINTIM('-',NEWS_MARK(2))
+	      REWRITE (23,IOSTAT=IER) NEWS_MARK
+	   END IF
+	END IF
+
+	IF (IER.NE.0.AND.IER.NE.FOR$IOS_FILNOTFOU) THEN
+	   WRITE (6,'('' Unable to open mark file.'')')
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	   RETURN
+	END IF
+
+	IF (BULL_NEWS_TAG) THEN
+	   OLD_NEWS_NUMBER = 0
+	   NEWS_MARK(1) = 0
+	   FOLDER_NUMBER_SAVE = NEWS_FOLDER_NUMBER
+	   CALL OPEN_BULLNEWS_SHARED
+	   DO WHILE (IER.EQ.0)
+	      DO WHILE (REC_LOCK(IER))
+		 READ (23,KEYGT=NEWS_MARK(1),IOSTAT=IER) NEWS_MARK
+	      END DO
+	      IF (IER.EQ.0.AND.NEWS_NUMBER.NE.0) THEN
+		 IF (NEWS_NUMBER.NE.OLD_NEWS_NUMBER) THEN
+		    NEWS_FOLDER_NUMBER = NEWS_NUMBER
+		    SUBNUM = NEWS_FIND_SUBSCRIBE()
+		    IF (SUBNUM.GT.FOLDER_MAX-1) THEN
+		       DELETE (UNIT=23)
+		    ELSE
+		       OLD_NEWS_NUMBER = NEWS_NUMBER
+		       CALL READ_FOLDER_FILE_KEYNUM_TEMP
+     &			  (NEWS_FOLDER_NUMBER,IER1)
+		       IF (IER1.NE.0) THEN
+	      		  CALL ERRSNS(IDUMMY,IER2)
+		          IF (IER2.NE.RMS$_RNF) SUBNUM = 0
+		       ELSE
+			  DO I=1,2
+		             NEWS_TAG(1,I,SUBNUM) = F1_START
+		             NEWS_TAG(2,I,SUBNUM) = F1_NBULL
+		             NEWS_TAG(4,I,SUBNUM) = 0
+		             CALL LIB$GET_VM((F1_NBULL-F1_START)/8+1,
+     &					  NEWS_TAG(3,I,SUBNUM))
+		             CALL ZERO_VM((F1_NBULL-F1_START)/8+1,
+     &					%VAL(NEWS_TAG(3,I,SUBNUM)))
+			  END DO
+		       END IF
+		    END IF
+		 END IF
+		 IF (NEWS_NUMBER.EQ.OLD_NEWS_NUMBER) THEN
+	            IF (SUBNUM.EQ.0) THEN
+		       DELETE (UNIT=23)
+		    ELSE
+		       UNLOCK 23
+		       IF (NEWS_REC.GT.0) THEN
+			  TAG_TYPE = 1
+		       ELSE
+			  TAG_TYPE = 2
+		       END IF
+		       IF (NEWS_FORMAT.EQ.0) THEN	! 16 bit numbers
+		          DO I=5,256
+		             CALL SET_NEWS_TAG(INT(NEWS_MARK2(I)),SUBNUM,
+     &					   TAG_TYPE)
+		          END DO
+		       ELSE
+		          DO I=3,128
+		             CALL SET_NEWS_TAG(NEWS_MARK(I),SUBNUM,TAG_TYPE)
+		          END DO
+		       END IF
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   NEWS_FOLDER_NUMBER = FOLDER_NUMBER_SAVE
+	   CALL CLOSE_BULLNEWS
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_NEWS_TAG(NUM,SUBNUM,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	IF (NUM.GT.0) THEN
+	   LAST_NUM = NUM
+	   IF (NUM.LT.NEWS_TAG(1,TAG_TYPE,SUBNUM).OR.
+     &	       NUM.GT.NEWS_TAG(2,TAG_TYPE,SUBNUM)) RETURN
+	   CALL SET_TAG(NUM,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	ELSE IF (NUM.LT.0) THEN
+	   IF (-NUM.LT.NEWS_TAG(1,TAG_TYPE,SUBNUM)) RETURN
+	   DO J=MAX(NEWS_TAG(1,TAG_TYPE,SUBNUM),LAST_NUM+1),
+     &		MIN(NEWS_TAG(2,TAG_TYPE,SUBNUM),-NUM)
+	      CALL SET_TAG(J,%VAL(NEWS_TAG(3,TAG_TYPE,SUBNUM)),
+     &		NEWS_TAG(1,TAG_TYPE,SUBNUM))
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE OPEN_NEW_TAG(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+
+	CHARACTER*12 BULL_MARK_DIR
+
+	DIMENSION BTIM(2)
+	CHARACTER KEY*8
+
+	IER = SYS_TRNLNM('BULL_MARK',BULL_PARAMETER)
+	IF (IER) THEN
+	   BULL_MARK_DIR = 'BULL_MARK:'
+	ELSE
+	   BULL_MARK_DIR = 'SYS$LOGIN:'
+	END IF
+
+	IER1 = SYS_TRNLNM_SYSTEM('BULL_MARK',BULL_PARAMETER)
+	IF (.NOT.IER1) THEN
+	   IER = SYS_TRNLNM('BULL_MARK',BULL_PARAMETER)
+	   CALL DISABLE_PRIVS
+	   IER1 = .FALSE.
+	END IF
+	IF (REMOTE_SET.LT.3) THEN
+	   MARKUNIT = 13
+	   OPEN (UNIT=MARKUNIT,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.BULLMARK',STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	        RECORDSIZE=3,
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:12:CHARACTER))
+	   IF (IER.EQ.0) THEN
+	      CALL SYS_BINTIM('-',BTIM)
+	      CALL GET_MSGKEY(BTIM,KEY)
+	      WRITE (13) TAG_KEY('FFFF'X,KEY,0)
+	   END IF
+	ELSE
+	   MARKUNIT = 23
+	   OPEN (UNIT=MARKUNIT,FILE=BULL_MARK_DIR//
+     &	        USERNAME(:TRIM(USERNAME))//'.NEWSMARK',STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',SHARED,
+     &	        RECORDSIZE=128,
+     &	        FORM='UNFORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:4:INTEGER))
+	   IF (IER.EQ.0) THEN
+	      NEWS_MARK(1) = 0
+	      CALL SYS_BINTIM('-',NEWS_MARK(2))
+	      WRITE (23,IOSTAT=IER) NEWS_MARK
+           END IF
+ 	END IF
+	IF (.NOT.IER1) CALL ENABLE_PRIVS
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' Cannot create mark file.'')')
+	   CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	      IER = 0
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	      IER = IER1
+	   END IF
+	ELSE
+	   IF (.NOT.IER1) THEN
+	      INQUIRE (UNIT=MARKUNIT,NAME=BULL_PARAMETER)
+	      WRITE (6,'('' Created MARK file: '',A)')
+     &		BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+	   END IF
+	   IF (MARKUNIT.EQ.13) BULL_TAG = 1
+	   IF (MARKUNIT.EQ.23) BULL_NEWS_TAG = .TRUE.
+	   IER = 1
+	END IF
+
+	RETURN
+	END
+
+
+
+	CHARACTER*12 FUNCTION TAG_KEY(FOLDER_NUMBER,MSG_KEY,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) MSG_KEY
+
+	IF (TAG_TYPE.EQ.1) THEN
+	   CALL LIB$MOVC3(4,FOLDER_NUMBER,%REF(TAG_KEY))
+	ELSE
+	   CALL LIB$MOVC3(4,-(1+FOLDER_NUMBER),%REF(TAG_KEY))
+	END IF
+
+	CALL GET_MSGKEY(%REF(MSG_KEY),TAG_KEY(5:))
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_FIRST_TAG(FOLDER_NUMBER,IER,MESSAGE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*12 TAG_KEY,INPUT_KEY
+
+	CHARACTER*8 NEXT_MSG_KEY
+
+	IF ((.NOT.BULL_TAG.AND.REMOTE_SET.LT.3)
+     &	    .OR.(.NOT.BULL_NEWS_TAG.AND.REMOTE_SET.GE.3)) THEN
+	   CALL OPEN_NEW_TAG(IER)
+	   IF (.NOT.IER) RETURN
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+	   CALL GET_FIRST_NEWS_TAG(IER,MESSAGE)
+	   RETURN
+	END IF
+
+	IF (BTEST(READ_TAG,3)) THEN
+	   MSG_NUM = 0
+ 	   CALL GET_NEXT_UNTAG(FOLDER_NUMBER,IER,MESSAGE,DUMMY)
+	   IF (IER.EQ.0) THEN
+	      MESSAGE = MESSAGE - 1
+	      MSG_NUM = MESSAGE
+	      MSG_KEY = BULLDIR_HEADER
+	   END IF
+	   RETURN
+	END IF
+
+	MSG_KEY = BULLDIR_HEADER
+
+	HEADER = .TRUE.
+
+	DO J=1,2
+	   IF (BTEST(READ_TAG,J)) I = J
+	END DO
+
+	CALL CONFIRM_TAG(IER,FOLDER_NUMBER,MESSAGE,HEADER,I)
+
+	RETURN
+
+	ENTRY GET_THIS_TAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+
+	IF (REMOTE_SET.GE.3) THEN
+	   CALL GET_THIS_NEWS_TAG(IER,MESSAGE,TAG_TYPE)
+	   RETURN
+	END IF
+
+	TAG_TYPE = 0
+
+	DO I=1,2
+	   IF (BTEST(READ_TAG,I).OR.BTEST(READ_TAG,3)) THEN
+	      DO WHILE (REC_LOCK(IER))
+	         READ (13,KEY=TAG_KEY(FOLDER_NUMBER,MSG_KEY,I),
+     &		   IOSTAT=IER) INPUT_KEY
+	      END DO
+	      IF (IER.EQ.0) TAG_TYPE = IBSET(TAG_TYPE,I)
+	   END IF
+	END DO
+
+	IF ((TAG_TYPE.NE.0.AND..NOT.BTEST(READ_TAG,3)).OR.
+     &	    (BTEST(READ_TAG,3).AND.
+     &	     (.NOT.BTEST(TAG_TYPE,2).OR..NOT.BTEST(READ_TAG,2)).AND.
+     &	     (.NOT.BTEST(TAG_TYPE,1).OR..NOT.BTEST(READ_TAG,1)))) THEN
+	   IF (IER.EQ.0) UNLOCK 13
+	   IER = 0
+	   MESSAGE = MSG_NUM
+	ELSE
+	   IER = 36
+	END IF
+
+	RETURN
+
+	ENTRY GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+
+	MSG_NUM = MSG_NUM - 1
+
+	CALL DECREMENT_MSG_KEY
+
+	ENTRY GET_NEXT_TAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+
+	IF (REMOTE_SET.GE.3) THEN
+	   MSG_NUM = ABS(MSG_NUM) + 1
+	   CALL GET_THIS_OR_NEXT_NEWS_TAG(MSG_NUM,IER,MESSAGE,TAG_TYPE)
+	   RETURN
+	END IF
+
+	IER = 36
+
+	HEADER = .FALSE.
+
+	TAG_TYPE = 0
+
+	IF (BTEST(READ_TAG,3)) THEN
+	   CALL GET_NEXT_UNTAG(FOLDER_NUMBER,IER,MESSAGE,TAG_TYPE)
+	   RETURN
+	END IF
+
+	DO WHILE (IER.NE.0)
+	   I = 0
+	   DO J=1,2
+	      IF (BTEST(READ_TAG,J)) THEN
+	         DO WHILE (REC_LOCK(IER))
+	            READ (13,KEYGT=TAG_KEY(FOLDER_NUMBER,MSG_KEY,J),
+     &		        IOSTAT=IER) INPUT_KEY
+		 END DO
+		 IF (IER.EQ.0) THEN
+	            CALL LIB$MOVC3(4,%REF(INPUT_KEY),FOLDER1_NUMBER)
+		    IF ((J.EQ.1.AND.FOLDER1_NUMBER.NE.FOLDER_NUMBER).OR.
+     &		      (J.EQ.2.AND.FOLDER1_NUMBER.NE.-(1+FOLDER_NUMBER)))
+     &		      IER = 36
+		 END IF
+		 IF (IER.EQ.0) THEN
+		    IF (J.EQ.1) THEN
+		       NEXT_MSG_KEY = INPUT_KEY(5:)
+		       I = 1
+		    ELSE IF (I.EQ.0.OR.COMPARE_MSG_KEY(NEXT_MSG_KEY,
+     &			     INPUT_KEY(5:)).GT.0) THEN
+		       I = 2
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   IF (I.EQ.0) RETURN
+	   NEXT_MSG_KEY = MSG_KEY
+	   CALL CONFIRM_TAG(IER,FOLDER_NUMBER,MESSAGE,HEADER,I)
+	   IF (IER.EQ.0) THEN
+	      TAG_TYPE = IBSET(TAG_TYPE,I)
+	      DO WHILE (REC_LOCK(IER))
+	         READ (13,KEY=TAG_KEY(FOLDER_NUMBER,MSG_KEY,3-I),
+     &		        IOSTAT=IER) INPUT_KEY
+	      END DO
+	      IF (IER.EQ.0) TAG_TYPE = IBSET(TAG_TYPE,3-I)
+	      IER = 0
+	      RETURN
+	   ELSE IF (.NOT.BTEST(READ_TAG,3-I)) THEN
+	      MSG_KEY = NEXT_MSG_KEY
+	      RETURN
+	   ELSE
+	      MSG_KEY = NEXT_MSG_KEY
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_NEXT_UNTAG(FN,IER,MESSAGE,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	CLOSE_IT = .NOT.CLOSE_IT
+	IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+
+	DO MESSAGE = MSG_NUM+1,F_NBULL
+	   CALL READDIR(MESSAGE,IER)
+	   IF (IER.EQ.MESSAGE+1) THEN
+	      CALL GET_THIS_TAG(FN,IER,DUMMY,TAG_TYPE)
+	      IF (IER.EQ.0) THEN
+		 IER = 0
+		 IF (CLOSE_IT) CALL CLOSE_BULLDIR
+		 RETURN
+	      END IF
+	   END IF
+	END DO
+
+	IER = 36
+	IF (CLOSE_IT) CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION COMPARE_MSG_KEY(MSG_KEY1,MSG_KEY2)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*8 MSG_KEY1,MSG_KEY2
+
+	DIMENSION BTIM1(2),BTIM2(2)
+
+	CALL GET_MSGBTIM(MSG_KEY1,BTIM1)
+	CALL GET_MSGBTIM(MSG_KEY2,BTIM2)
+
+	COMPARE_MSG_KEY = COMPARE_BTIM(BTIM1,BTIM2)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CONFIRM_TAG(IER,FOLDER_NUMBER,MESSAGE,HEADER,J)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER*12 TAG_KEY,INPUT_KEY
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (13,KEYGT=TAG_KEY(FOLDER_NUMBER,MSG_KEY,J),IOSTAT=IER)
+     &					INPUT_KEY
+	END DO
+
+	CLOSE_IT = .FALSE.
+
+	DO WHILE (FOLDER_NUMBER.GT.0)
+	   IF (IER.EQ.0) THEN
+	      CALL GET_MSGKEY(%REF(INPUT_KEY(5:)),MSG_KEY)
+	      CALL LIB$MOVC3(4,%REF(INPUT_KEY),FOLDER1_NUMBER)
+	   END IF
+
+	   IF (IER.EQ.0) THEN
+	      IF ((J.EQ.1.AND.FOLDER1_NUMBER.NE.FOLDER_NUMBER).OR.
+     &		  (J.EQ.2.AND.FOLDER1_NUMBER.NE.-(1+FOLDER_NUMBER)))
+     &		  IER = 36
+	   END IF
+	   IF (IER.NE.0) THEN
+	      IER = 1
+	      UNLOCK 13
+	      IF (CLOSE_IT) CALL CLOSE_BULLDIR
+	      RETURN
+	   ELSE
+	      CALL DECREMENT_MSG_KEY
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      INQUIRE (UNIT=2,OPENED=IER)
+	      IF (.NOT.IER) THEN
+		 CALL OPEN_BULLDIR_SHARED
+		 CLOSE_IT = .TRUE.
+	      END IF
+	      CALL READDIR_KEYGE(IER)
+	      CALL GET_MSGKEY(%REF(INPUT_KEY(5:)),INPUT_KEY(5:))
+	      IF (IER.NE.0.AND.MSG_KEY.EQ.INPUT_KEY(5:)) THEN
+	         UNLOCK 13
+		 MESSAGE = MSG_NUM
+		 IF (HEADER) THEN
+		    MESSAGE = MESSAGE - 1
+		    MSG_NUM = MESSAGE
+		    MSG_KEY = BULLDIR_HEADER
+		 END IF
+		 IER = 0
+		 IF (CLOSE_IT) CALL CLOSE_BULLDIR
+	         RETURN
+	      ELSE
+		 DELETE (UNIT=13)
+		 IF (BTEST(READ_TAG,1).AND.BTEST(READ_TAG,2)) THEN
+		    IER = 36
+		    IF (CLOSE_IT) CALL CLOSE_BULLDIR
+		    RETURN
+		 END IF
+		 DO WHILE (REC_LOCK(IER))
+	            READ (13,IOSTAT=IER) INPUT_KEY
+	 	 END DO
+	      END IF
+	   END IF
+
+	END DO
+
+	END
+
+
+
+	SUBROUTINE CLOSE_TAG
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+
+	TAG_OPENED = .FALSE.
+
+	IF (BULL_NEWS_TAG) THEN
+	   DO I=1,FOLDER_MAX-1
+	      DO M=1,2
+	         IF (NEWS_TAG(3,M,I).NE.0.AND.NEWS_TAG(4,M,I).EQ.1) THEN
+	            IF (.NOT.TAG_OPENED) THEN
+		       CALL OPEN_OLD_TAG
+		       TAG_OPENED = .TRUE.
+		    END IF
+		    IF (M.EQ.1) THEN
+		       NEWS_REC = 1
+		    ELSE
+		       NEWS_REC = -32767
+		    END IF
+	            NEWS_FORMAT = 0
+		    IF (NEWS_TAG(2,M,I).GT.32767) NEWS_FORMAT = 1
+		    LIMIT = 256/(NEWS_FORMAT+1)
+	            NEWS_NUMBER = LAST_NEWS_READ2(1,I)
+		    K = 5-NEWS_FORMAT*2
+		    SET_LIST = .FALSE.
+		    DO J=NEWS_TAG(1,M,I),NEWS_TAG(2,M,I)
+		       IF (TEST_TAG(J,%VAL(NEWS_TAG(3,M,I)),
+     &				      NEWS_TAG(1,M,I))) THEN
+		          IF (.NOT.SET_LIST) THEN
+		             CALL SET_NEWS_MARK(K,J)
+			     LAST_SET = J
+			     K = K + 1
+		             SET_LIST = .TRUE.
+		          END IF
+		       ELSE IF (SET_LIST) THEN
+		          IF (LAST_SET.NE.J-1) THEN
+			     CALL SET_NEWS_MARK(K,-(J-1))
+		             K = K + 1
+			  END IF
+		          SET_LIST = .FALSE.
+		       END IF
+		       IF (J.EQ.NEWS_TAG(2,M,I)) THEN
+		          IF (SET_LIST.AND.LAST_SET.NE.J) THEN
+			     CALL SET_NEWS_MARK(K,-J)
+		             K = K + 1
+		          END IF
+		          DO L=K,LIMIT
+			     CALL SET_NEWS_MARK(L,0)
+		          END DO
+		          K = LIMIT + 1
+		       END IF
+		       IF (K.GT.LIMIT) THEN
+		          DO WHILE (REC_LOCK(IER))
+		             READ (23,KEYEQ=NEWS_MARK(1),IOSTAT=IER)
+		          END DO
+		          IF (IER.NE.0) THEN
+		             WRITE (23,IOSTAT=IER) NEWS_MARK
+		          ELSE
+		             REWRITE (23,IOSTAT=IER) NEWS_MARK
+		          END IF
+		          K = 5-NEWS_FORMAT*2
+		          NEWS_REC = NEWS_REC + 1
+		          IF (J.EQ.NEWS_TAG(2,M,I)) THEN
+		             DO WHILE (REC_LOCK(IER))
+		                READ (23,KEYEQ=NEWS_MARK(1),IOSTAT=IER)
+			        IF (IER.EQ.0) THEN
+			           DELETE (UNIT=23)
+				   NEWS_REC = NEWS_REC + 1
+				   L = REC_LOCK(IER)
+			        END IF
+			     END DO
+		          END IF
+		       END IF
+		    END DO
+	         END IF
+	      END DO
+	   END DO
+	   CLOSE (UNIT=23)
+	END IF
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET_NEWS_MARK(I,J)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	IF (NEWS_FORMAT.EQ.0) THEN
+	   NEWS_MARK2(I) = J
+	ELSE
+	   NEWS_MARK(I) = J
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ZERO_VM(NUM,NEWS_TAG)
+
+	IMPLICIT INTEGER (A-Z)
+
+	LOGICAL*1 NEWS_TAG(1)
+
+	DO I=1,NUM
+	   NEWS_TAG(I) = 0
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FREE_TAGS(ISUB)
+
+        IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /NEWS_TAGS/ NEWS_TAG(4,2,FOLDER_MAX-1)
+	COMMON /NEWS_MARK/ NEWS_MARK
+	DIMENSION NEWS_MARK(128)
+	INTEGER*2 NEWS_MARK2(256),NEWS_NUMBER,NEWS_REC
+	EQUIVALENCE (NEWS_MARK(1),NEWS_MARK2(1))
+	EQUIVALENCE (NEWS_MARK2(2),NEWS_NUMBER)
+	EQUIVALENCE (NEWS_MARK2(1),NEWS_REC)
+	EQUIVALENCE (NEWS_MARK(2),NEWS_FORMAT)
+
+	DO I=1,2
+	   IF (NEWS_TAG(3,I,ISUB).GT.0) THEN
+	      CALL LIB$FREE_VM(
+     &		(NEWS_TAG(2,I,ISUB)-NEWS_TAG(1,I,ISUB))/8+1,NEWS_TAG(3,I,ISUB))
+	      NEWS_TAG(3,I,ISUB) = 0
+	      NEWS_NUMBER = NEWS_FOLDER_NUMBER
+	      NEWS_REC = -32768
+	      DO WHILE (REC_LOCK(IER))
+	         READ (23,KEYGT=NEWS_MARK(1),IOSTAT=IER) NEWS_MARK
+	         IF (IER.EQ.0.AND.NEWS_NUMBER.EQ.NEWS_FOLDER_NUMBER) THEN
+		    DELETE (UNIT=23)
+		    L = REC_LOCK(IER)
+	         END IF
+	      END DO
+	      IF (IER.EQ.0) UNLOCK 23
+	   END IF
+
+	   DO J=I,FOLDER_MAX-2
+	      CALL LIB$MOVC3(16,NEWS_TAG(1,I,J+1),NEWS_TAG(1,I,J))
+	   END DO
+
+	   DO J=1,4
+	      NEWS_TAG(J,I,FOLDER_MAX-1) = 0
+	   END DO
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_PREVIOUS_TAG(FN,IER,BULL_READ,TAG_TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	CHARACTER*8 PREV_MSG_KEY
+
+	IER = 36
+
+	IF (REMOTE_SET.GE.3) THEN
+	   INQUIRE (UNIT=2,OPENED=CLOSE_IT)
+	   CLOSE_IT = .NOT.CLOSE_IT
+	   IF (CLOSE_IT) CALL OPEN_BULLDIR_SHARED
+	   SUBNUM = NEWS_FIND_SUBSCRIBE()
+	   DO WHILE (IER.NE.0.AND.MSG_NUM.GT.F_START)
+	      MSG_NUM = MSG_NUM - 1
+	      CALL GET_THIS_TAG(FN,IER,MSG_NUM,TAG_TYPE)
+	      IF (IER.EQ.0) THEN
+		 TMP_MSG_NUM = MSG_NUM
+	         CALL READDIR(TMP_MSG_NUM,IER1)
+	         IF (IER1.NE.MSG_NUM+1) THEN
+	            IF (.NOT.BTEST(READ_TAG,3)) THEN
+		       CALL DEL_NEWS_TAG(TAG_TYPE,TMP_MSG_NUM,SUBNUM)
+		    END IF
+		    IER = 36
+	         END IF
+	      END IF
+	   END DO
+	   BULL_READ = MSG_NUM
+	   IF (CLOSE_IT) CALL CLOSE_BULLDIR 
+	ELSE
+	   IF (MSG_NUM.EQ.0) RETURN
+	   SAVE_MSG_NUM = MSG_NUM
+	   PREV_MSG_NUM = MSG_NUM
+	   MSG_NUM = 0
+	   MSG_KEY = BULLDIR_HEADER
+	   IER = 0
+	   DO WHILE (IER.EQ.0.AND.MSG_NUM.LT.SAVE_MSG_NUM)
+	      IF (MSG_NUM.GT.0) THEN
+	         PREV_MSG_KEY = MSG_KEY
+	         PREV_MSG_NUM = MSG_NUM
+	      END IF
+	      CALL GET_NEXT_TAG(FN,IER,BULL_READ,TAG_TYPE)
+	   END DO
+	   IF (PREV_MSG_NUM.LT.SAVE_MSG_NUM) THEN
+	      MSG_NUM = PREV_MSG_NUM
+	      MSG_KEY = PREV_MSG_KEY
+	      CALL GET_THIS_OR_NEXT_TAG(FN,IER,BULL_READ,TAG_TYPE)
+	   ELSE
+	      IER = 36
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+	SUBROUTINE DECREMENT_MSG_KEY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	I = 1
+	DO WHILE (I.LT.9)
+	   ITEST = ICHAR(MSG_KEY(I:I))
+	   IF (ITEST.GT.0) THEN
+	      MSG_KEY(I:I) = CHAR(ITEST-1)
+	      I = 9
+	   ELSE
+	      I = I + 1
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_GENERIC(GENERIC)
+C
+C  SUBROUTINE SET_GENERIC
+C
+C  FUNCTION: Enables or disables "GENERIC" display, i.e. displaying
+C	general bulletins continually for a certain amount of days.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'(
+     &      '' ERROR: No privs to change GENERIC.'')')
+	   RETURN
+	END IF
+
+	IER = CLI$GET_VALUE('USERNAME',TEMP_USER)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_KEYNAME(TEMP_USER,IER)
+
+	IF (IER.EQ.0) THEN
+	   IF (GENERIC) THEN
+	      IF (CLI$PRESENT('DAYS')) THEN
+	         IER = CLI$GET_VALUE('DAYS',BULL_PARAMETER)
+	         CALL LIB$MOVC3(4,%REF(BULL_PARAMETER),NEW_FLAG(2))
+	      ELSE
+		 NEW_FLAG(2) = '   7'
+	      END IF
+	   ELSE
+	      NEW_FLAG(2) = 0
+	   END IF
+	   REWRITE (4) TEMP_USER//USER_ENTRY(13:)
+	ELSE
+	   WRITE (6,'('' ERROR: Specified username not found.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET_BRIEF_CONTINUOUS(BRIEF_CONTINUOUS)
+C
+C  SUBROUTINE SET_BRIEF_CONTINUOUS
+C
+C  FUNCTION: Enables or disables "BRIEF_CONTINUOUS" display, i.e. displaying
+C	the brief message continually until the new messages have been read.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+
+	IF (BRIEF_CONTINUOUS) THEN
+	   NEW_FLAG(2) = -1
+	ELSE
+	   NEW_FLAG(2) = 0
+	END IF
+
+	IF (IER.EQ.0) REWRITE (4) USER_ENTRY
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET_LOGIN(LOGIN)
+C
+C  SUBROUTINE SET_LOGIN
+C
+C  FUNCTION: Enables or disables bulletin display at login.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER TODAY*24
+
+	DIMENSION NOLOGIN_BTIM(2)
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'(
+     &      '' ERROR: No privs to change LOGIN.'')')
+	   RETURN
+	END IF
+
+	IER = CLI$GET_VALUE('USERNAME',TEMP_USER)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	CALL READ_USER_FILE_KEYNAME(TEMP_USER,IER)
+
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NOLOGIN_BTIM)
+	IF (IER.EQ.0) THEN
+	   IF (LOGIN.AND.COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM).GE.0) THEN
+	      CALL SYS_BINTIM(TODAY,LOGIN_BTIM)
+	   ELSE IF (.NOT.LOGIN) THEN
+	      LOGIN_BTIM(1) = NOLOGIN_BTIM(1)
+	      LOGIN_BTIM(2) = NOLOGIN_BTIM(2)
+	   END IF
+	   REWRITE (4) TEMP_USER//USER_ENTRY(13:)
+	ELSE
+	   WRITE (6,'('' ERROR: Specified username not found.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_UAF(USERNAME,USER,GROUP,ACCOUNT,FLAGS,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER USERNAME*(*),ACCOUNT*(*)
+
+	INCLUDE '($UAIDEF)'
+
+	INTEGER*2 UIC(2)
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(4,UAI$_FLAGS,%LOC(FLAGS))
+	CALL ADD_2_ITMLST(LEN(ACCOUNT),UAI$_ACCOUNT,%LOC(ACCOUNT))
+	CALL ADD_2_ITMLST(4,UAI$_UIC,%LOC(UIC))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+
+	USER = UIC(1)
+	GROUP = UIC(2)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DCLEXH(EXIT_ROUTINE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER*4 EXBLK(4)
+
+	EXBLK(2) = EXIT_ROUTINE
+	EXBLK(3) = 1
+	EXBLK(4) = %LOC(EXBLK(4))
+
+	CALL SYS$DCLEXH(EXBLK(1))
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SENDMAIL(FILE,TO,SUBJECT,STATUS)
+
+        IMPLICIT INTEGER (A-Z)
+
+	PARAMETER CRLF = CHAR(13)//CHAR(10)
+
+	INCLUDE '($MAILDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /MAIL_INFO/ USE_INFROM
+	DATA USE_INFROM /.FALSE./
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+	DATA HEADER_Q1/0/
+
+	COMMON /SENDTO/ SENDTO
+	CHARACTER*256 SENDTO
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	CHARACTER*(*) FILE,TO,SUBJECT
+
+	EXTERNAL MAIL_ERROR
+
+	CALL SYS$SETAST(%VAL(1))
+
+	CALL DISABLE_PRIVS
+
+	SENDTO = TO
+        DO WHILE (INDEX(SENDTO,'""').GT.0)
+           SENDTO = SENDTO(:INDEX(SENDTO,'""'))//
+     &                   SENDTO(INDEX(SENDTO,'""')+2:)
+        END DO
+
+	DO WHILE (INDEX(SUBJECT,'""').GT.0)
+	   SUBJECT = SUBJECT(:INDEX(SUBJECT,'""'))//
+     &			 SUBJECT(INDEX(SUBJECT,'""')+2:)
+	END DO	
+
+	IF (USE_INFROM.AND.(SYS_TRNLNM('TWF$TCP','DEFINED').OR.
+     &	    SYS_TRNLNM('MULTINET_SOCKET_LIBRARY','DEFINED').OR.
+     &	    SYS_TRNLNM('UCX$DEVICE','DEFINED'))
+     &	    .AND..NOT.SYS_TRNLNM('BULL_DISABLE_SMTP','DEFINED')) THEN
+	   IER = SYS$ASCTIM(,INPUT,,)
+	   INPUT = INPUT(:2)//INPUT(4:6)//INPUT(10:11)//
+     &	      INPUT(13:14)//INPUT(16:17)//INPUT(19:20)//
+     &	      INPUT(22:23)
+	   IF (INPUT(:1).EQ.' ') INPUT = INPUT(2:)
+	   OPEN (UNIT=8,FILE=FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		INPUT(:TRIM(INPUT))//'.SMTP',IOSTAT=IER1,
+     &		STATUS='NEW',RECL=256)
+	   IF (IER1.EQ.0) THEN
+	      IF (LPATH.EQ.0) CALL GET_PATHNAME
+	      WRITE (8,'(A)',IOSTAT=IER) 'helo '//PATHNAME(:LPATH)
+	      INPUT = INFROM
+	      I = INDEX(INPUT,'<')
+	      IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN 
+		 INPUT = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+	      END IF
+	      WRITE (8,'(A)',IOSTAT=IER) 'MAIL FROM:<'//
+     &					INPUT(:TRIM(INPUT))//'>'
+	      SENDTO = SENDTO(INDEX(SENDTO,'"')+1:)
+	      DO WHILE (INDEX(SENDTO,'"').GT.0)
+		 SENDTO = SENDTO(:INDEX(SENDTO,'"')-1)//
+     &			  SENDTO(INDEX(SENDTO,'"')+1:)
+	      END DO
+	      WRITE (8,'(A)',IOSTAT=IER) 'RCPT TO:<'//SENDTO(:TRIM(SENDTO))
+     &					//'>'
+	      WRITE (8,'(A)',IOSTAT=IER) 'DATA'
+	      HEADER_Q = HEADER_Q1
+	      DO I=1,NHEAD
+		 CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+		 WRITE (8,'(A)',IOSTAT=IER) INPUT(:TRIM(INPUT))
+	      END DO
+	      IF (NHEAD.EQ.0.AND.TRIM(SUBJECT).GT.0) THEN
+		 WRITE (8,'(A)',IOSTAT=IER)
+     &			'Subject: '//SUBJECT(:TRIM(SUBJECT))
+		 WRITE (8,'(A)',IOSTAT=IER)
+	      END IF
+	      OPEN (UNIT=3,FILE=FILE,STATUS='OLD',IOSTAT=IER)
+	      DO WHILE (IER.EQ.0)
+		 READ (3,'(Q,A)',IOSTAT=IER) L,INPUT
+		 IF (IER.EQ.0) THEN
+		    WRITE (8,'(A)',IOSTAT=IER) INPUT(:L)
+		 END IF
+	      END DO
+	      CLOSE (UNIT=3)
+	      REWIND (UNIT=8,IOSTAT=IER)
+	      IF (IER.NE.0) THEN
+	         CLOSE (UNIT=8,STATUS='DELETE')
+	         IER1 = 2
+	      END IF
+	   END IF
+	   IF (.NOT.SMTP_CONNECT()) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'220') GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('helo '//PATHNAME(2:LPATH)//CRLF))
+     &	       GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'250') GOTO 10
+	   INPUT = INFROM
+	   I = INDEX(INPUT,'<')
+	   IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN 
+	       INPUT = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+	   ELSE IF (I.EQ.0.AND.INDEX(INPUT,'@').EQ.0) THEN
+	       INPUT = INPUT(:TRIM(INPUT))//PATHNAME(:LPATH)
+	   END IF
+	   IF (.NOT.SMTP_WRITE_PACKET('MAIL FROM:<'//INPUT(:TRIM(INPUT))
+     &	       //'>'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'250') GOTO 10
+	   SENDTO = SENDTO(INDEX(SENDTO,'"')+1:)
+	   DO WHILE (INDEX(SENDTO,'"').GT.0)
+	      SENDTO = SENDTO(:INDEX(SENDTO,'"')-1)//
+     &			     SENDTO(INDEX(SENDTO,'"')+1:)
+	   END DO
+	   IF (.NOT.SMTP_WRITE_PACKET('RCPT TO:<'//SENDTO(:TRIM(SENDTO))
+     &				   //'>'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'250') GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('DATA'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'354') GOTO 10
+	   HEADER_Q = HEADER_Q1
+	   DO I=1,NHEAD
+	      CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+	      IF (BTEST(FOLDER_FLAG,15).OR.INPUT(:8).NE.'Subject:') THEN
+	         IF (.NOT.SMTP_WRITE_PACKET(INPUT(:TRIM(INPUT))//CRLF))
+     &		    GOTO 10
+	      ELSE
+	         IF (.NOT.SMTP_WRITE_PACKET('Subject: '//
+     &		    SUBJECT(:TRIM(SUBJECT))//CRLF)) GOTO 10
+	      END IF
+	   END DO
+	   IF (NHEAD.EQ.0.AND.TRIM(SUBJECT).GT.0) THEN
+	      IF (.NOT.SMTP_WRITE_PACKET('Subject: '//
+     &		    SUBJECT(:TRIM(SUBJECT))//CRLF)) GOTO 10
+	      NHEAD = 1
+	   END IF
+	   IF (NHEAD.GT.0.AND..NOT.SMTP_WRITE_PACKET(CRLF)) GOTO 10
+	   OPEN (UNIT=3,FILE=FILE,STATUS='OLD',IOSTAT=IER2)
+	   DO WHILE (IER2.EQ.0)
+	      READ (3,'(Q,A)',IOSTAT=IER2) L,INPUT
+	      IF (IER2.EQ.0) THEN
+		 IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) IER2 = 2
+	      END IF
+	   END DO
+	   CLOSE (UNIT=3)
+	   IF (IER2.EQ.2) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('.'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('QUIT'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IER2 = 1
+	   GOTO 20
+10	   IER2 = 2
+20	   CALL SMTP_DISCONNECT()
+	   IF (IER1.EQ.0) THEN
+	      IF (IER2) THEN
+		 CLOSE (UNIT=8,STATUS='DELETE')
+	      ELSE
+		 CLOSE (UNIT=8)
+	      END IF
+	   END IF
+	   CALL ENABLE_PRIVS
+	   STATUS = 1
+	   RETURN
+	END IF
+
+	C = 0
+
+	CALL LIB$ESTABLISH(MAIL_ERROR)
+
+	STATUS = MAIL$SEND_BEGIN(C,0,0)
+	IF (.NOT.STATUS) GO TO 100
+
+	J = 1
+	DO WHILE (J.LE.TRIM(SENDTO))
+	   I = INDEX(SENDTO(J:),',') - 1
+	   IF (I.EQ.-1) I = TRIM(SENDTO(J:))
+           CALL INIT_ITMLST
+           CALL ADD_2_ITMLST(I,MAIL$_SEND_USERNAME,%LOC(SENDTO(J:)))
+           CALL END_ITMLST(ADDRESS_ITMLST)
+
+           STATUS = MAIL$SEND_ADD_ADDRESS(C,%VAL(ADDRESS_ITMLST),0)
+           IF (.NOT.STATUS) GO TO 100
+	   J = J + I
+	   IF (SENDTO(J:J).EQ.',') J = J + 1
+	END DO
+
+        CALL INIT_ITMLST
+        CALL ADD_2_ITMLST(TRIM(SUBJECT),MAIL$_SEND_SUBJECT
+     &				,%LOC(SUBJECT))
+        CALL ADD_2_ITMLST(TRIM(SENDTO),MAIL$_SEND_TO_LINE,%LOC(SENDTO))
+        CALL END_ITMLST(ATTRIBUTE_ITMLST)
+
+        STATUS = MAIL$SEND_ADD_ATTRIBUTE(C,%VAL(ATTRIBUTE_ITMLST),0)
+        IF (.NOT.STATUS) GO TO 100
+                                        
+        CALL INIT_ITMLST
+        CALL ADD_2_ITMLST(TRIM(FILE),MAIL$_SEND_FILENAME,%LOC(FILE))
+        CALL END_ITMLST(BODYPART_ITMLST)
+
+        STATUS = MAIL$SEND_ADD_BODYPART(C,%VAL(BODYPART_ITMLST),0)
+        IF (.NOT.STATUS) GO TO 100
+
+        STATUS = MAIL$SEND_MESSAGE(C,0,0)
+        IF (.NOT.STATUS) GO TO 100
+
+        STATUS = MAIL$SEND_END(C,0,0)
+        IF (.NOT.STATUS) GO TO 100
+
+100	CALL ENABLE_PRIVS
+	CALL LIB$REVERT
+
+        RETURN
+        END
+
+
+
+	FUNCTION MAIL_ERROR(SIGARGS,MECHARGS)
+
+	MAIL_ERROR = .TRUE.
+
+	CALL SYS$PUTMSG(SIGARGS,,)
+
+	RETURN
+	END
+
+
+
+
+        SUBROUTINE SET_NEWS
+
+        IMPLICIT INTEGER (A-Z)
+
+        INCLUDE '($SSDEF)'
+
+        INCLUDE 'BULLUSER.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+
+        INCLUDE 'BULLFILES.INC'
+
+        COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+        CHARACTER*64 BULL_PARAMETER
+	
+	EXTERNAL CLI$_NEGATED,CLI$_ABSENT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+	CHARACTER*80 BULLNEWSDIR_FILE
+
+	DIMENSION EXPIRED(2)
+
+	CHARACTER GROUP*44,FOLDER_SAVE*44,NEW_NEWS_ACCESS*132
+	CHARACTER NEWS_ACCESS*132
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: No privs to change NEWS.'')')
+	   RETURN
+	END IF
+
+	ENTRY SHOW_NEWS
+
+	LIMIT = -2
+	IF (CLI$GET_VALUE('LIMIT',BULL_PARAMETER,LEN_P)) THEN
+	   IER = OTS$CVT_TI_L(BULL_PARAMETER(:LEN_P),LIMIT,,%VAL(1))
+	   IF (.NOT.IER.OR.LIMIT.LT.-1) THEN
+	      WRITE (6,'('' ERROR: Invalid value for LIMIT.'')')
+	      RETURN
+	   END IF   
+	END IF	
+
+        EXPIRE = -1
+        IF (CLI$GET_VALUE('EXPIRATION',BULL_PARAMETER,LEN_P)) THEN
+           IER = OTS$CVT_TI_L(BULL_PARAMETER(:LEN_P),EXPIRE,,%VAL(1))
+	   IF (.NOT.IER.OR.(EXPIRE.LE.0.AND.CLI$PRESENT('DEFAULT'))) THEN
+	      WRITE (6,'('' ERROR: Invalid value for EXPIRATION.'')')
+	      RETURN
+	   END IF   
+        END IF
+
+	IF (.NOT.(CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('CLASS').OR.
+     &		CLI$PRESENT('SHOW_FOLDER')).AND.REMOTE_SET.LT.3) THEN 
+	   WRITE (6,'('' ERROR: You have not selected a news group.'')')
+           RETURN
+        END IF
+
+	CALL OPEN_BULLNEWS_SHARED	! Open folder file
+
+	IF (CLI$PRESENT('DEFAULT')) THEN
+	   CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+	ELSE IF (CLI$GET_VALUE('CLASS',BULL_PARAMETER,LEN_P)) THEN
+	   BULL_PARAMETER = BULL_PARAMETER(:LEN_P)//'.'
+	   CALL STR$UPCASE(BULL_PARAMETER,BULL_PARAMETER)
+	   LEN_P = LEN_P + 1
+	   IF (LEN_P.GT.LEN(FOLDER)) THEN
+	      WRITE (6,'('' ERROR: Class name too long.'')')
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+	   END IF
+	   GROUP = BULL_PARAMETER(:LEN_P)
+           LG = LEN_P
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(BULL_PARAMETER(:LEN_P),
+     &					NEWCLASS)
+	   IF (CLI$PRESENT('DELETE')) THEN
+	      IF (NEWCLASS.NE.0) THEN
+	         WRITE (6,'('' ERROR: Class not found.'')')
+	      ELSE
+	         DELETE (7)
+		 WRITE (6,'('' Class deleted.'')')
+	      END IF
+              IF (BTEST(FOLDER1_FLAG,0)) THEN
+		 OPEN (UNIT=3,FILE=NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	     	 CLOSE (UNIT=3,DISPOSE='DELETE')
+              END IF
+	      RETURN
+	   ELSE IF (NEWCLASS.NE.0) THEN
+              CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+              DO WHILE (IER.EQ.0)
+                 DO WHILE (REC_LOCK(IER))
+                    READ (7,KEY=NEWS_F1_COUNT,KEYID=1,IOSTAT=IER)
+                 END DO
+                 IF (IER.EQ.0) NEWS_F1_COUNT = NEWS_F1_COUNT + 1
+              END DO
+	      FOLDER1_FLAG = NEWS_FLAG_DEFAULT
+	      FOLDER1_BBEXPIRE = NEWS_EXPIRE_DEFAULT
+              F1_EXPIRE_LIMIT = NEWS_EXPIRE_LIMIT_DEFAULT
+ 	      CALL SYS_BINTIM('6-NOV-2956 00:00:00.00',EXPIRED)
+              CALL GET_MSGKEY(EXPIRED,NEWS_F1_EXPIRED_DATE)
+	      CALL SYS_BINTIM('5-NOV-1956 00:00:00.00',EXPIRED)
+              CALL GET_MSGKEY(EXPIRED,NEWS_F1_CREATED_DATE)
+	      FOLDER1_NUMBER = NEWS_F1_COUNT
+	      FOLDER1 = BULL_PARAMETER
+ 	      FOLDER1_FLAG = IBSET(FOLDER1_FLAG,10)
+	      CALL WRITE_FOLDER_FILE_TEMP(IER)
+	      IF (IER.NE.0) THEN
+		 CALL CLOSE_BULLNEWS
+		 WRITE (6,'('' Unable to add entry.'')')
+                 RETURN
+	      END IF	      
+	      TEMP = FOLDER1_NUMBER
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(1000,IER)
+	      NEWS_F1_COUNT = TEMP
+	      REWRITE (7) NEWS_FOLDER1_COM
+ 	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(TEMP,IER)
+	   END IF	
+ 	ELSE
+	   IF (CLI$GET_VALUE('SHOW_FOLDER',FOLDER1).EQ.
+     &				%LOC(CLI$_ABSENT)) FOLDER1 = FOLDER
+	   IF (INDEX(FOLDER1,'.').GT.0) CALL LOWERCASE(FOLDER1)
+       	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR: Invalid news group.'')')
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+	   END IF
+	END IF
+
+ 	IF (EXPIRE.GE.0) FOLDER1_BBEXPIRE = EXPIRE
+	IF (LIMIT.GE.-1) F1_EXPIRE_LIMIT = LIMIT
+
+	CLASS = CLI$PRESENT('CLASS')
+	DEFAULT = CLI$PRESENT('DEFAULT')
+	ALL = CLI$PRESENT('ALL')
+ 	IF (CLASS.AND.INDEX(GROUP(:LG-1),'.').GT.0) ALL = .TRUE.
+	DISABLE = CLI$PRESENT('DISABLE')
+      	ENABLE = CLI$PRESENT('ENABLE')
+     	PRIVATE = CLI$PRESENT('PRIVATE')
+     	NOPRIVATE = CLI$PRESENT('PRIVATE').EQ.%LOC(CLI$_NEGATED)
+	
+	STORED = 0
+	IF (CLI$PRESENT('STORED')) THEN
+	   STORED = 1
+	   IF (.NOT.(CLASS.OR.DEFAULT).AND..NOT.BTEST(FOLDER1_FLAG,8)) THEN 
+	      F1_LAST = 0
+	      F1_COUNT = 0
+	      F1_START = 0
+	      F1_NBULL = 0
+	      NEWS_F1_FIRST = 0
+	      NEWS_F1_END = 0
+           END IF
+	   FOLDER1_FLAG = IBSET(FOLDER1_FLAG,8)
+	ELSE IF (CLI$PRESENT('STORED').EQ.%LOC(CLI$_NEGATED)) THEN   
+	   STORED = 2
+	   CALL GET_INPUT_PROMPT(BULL_PARAMETER,LEN_P,
+     &      'Are you sure you want to remove stored setting? '//
+     &	    '(Y/N with N as default): ')
+	   IF (BULL_PARAMETER(:1).NE.'y'.AND.BULL_PARAMETER(:1).NE.'Y') THEN
+	      WRITE (6,'('' Stored setting was not removed.'')')
+	      CALL CLOSE_BULLNEWS
+	      RETURN
+           END IF
+	   IF (DEFAULT) THEN
+	      CALL LIB$DELETE_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &			//'[.BULLNEWS*]*.*;*')
+	      CALL LIB$DELETE_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &			//'BULLNEWS*.DIR;*')
+	   ELSE IF (.NOT.CLASS.AND.BTEST(FOLDER1_FLAG,8)) THEN
+              CALL CLOSE_BULLNEWS
+	      FOLDER_SAVE = FOLDER
+	      IF (FOLDER_NUMBER.NE.FOLDER1_NUMBER) THEN
+                 FOLDER_NUMBER = FOLDER1_NUMBER
+                 CALL SELECT_FOLDER(.FALSE.,IER)
+	      END IF
+	      FOLDER = FOLDER_SAVE
+              CALL OPEN_BULLDIR
+	      CALL CLOSE_BULLDIR_DELETE
+              CALL OPEN_BULLNEWS_SHARED 
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(NEWS_FOLDER_NUMBER,IER)
+	      F1_START = 0
+	      F1_NBULL = 0
+	      F1_COUNT = 0 
+              F1_LAST = 0
+           END IF
+           FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,8)
+	   FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,13)
+        END IF
+
+	IF (NOPRIVATE.AND..NOT.DEFAULT) THEN
+	   OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	   CLOSE (UNIT=3,DISPOSE='DELETE')
+	   FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+	END IF
+
+	IF (PRIVATE.AND..NOT.BTEST(FOLDER1_FLAG,0)) THEN
+	   CALL SET_PROTECTION
+	   OPEN (UNIT=3,FILE=NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	   CLOSE (UNIT=3)
+	   IF (IER.NE.0) THEN	
+	      OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &			STATUS='NEW',IOSTAT=IER)
+	      CLOSE (UNIT=3)
+	   END IF
+	   CALL RESET_PROTECTION
+	   FOLDER1_FLAG = IBSET(FOLDER1_FLAG,0)
+	END IF
+
+	IF (ENABLE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,9)
+	IF (DISABLE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,9)
+
+	FLAG = ENABLE.OR.DISABLE.OR.STORED.NE.0.OR.PRIVATE.OR.NOPRIVATE
+
+        CALL REWRITE_FOLDER_FILE_TEMP(IER)
+
+        IF (DEFAULT.OR.(CLASS.AND.(STREQ(GROUP(:LG),FOLDER(:LG))
+     &		.OR.STREQ(GROUP(:LG-1),FOLDER)))) THEN 
+           NEWS_FLAG_DEFAULT = NEWS_F1_FLAG
+           NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+           NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	END IF
+
+        CALL OTS$CVT_L_TI(FOLDER1_BBEXPIRE,BULL_PARAMETER,,,)
+        IF (DEFAULT.OR.CLASS) THEN
+	   IF (CLASS) THEN
+              WRITE (6,'('' For class '',A,'':'')') GROUP(:LG)
+	   END IF
+           IF (BTEST(FOLDER1_FLAG,9)) WRITE (6,'('' Disable is set.'')')	
+           IF (BTEST(FOLDER1_FLAG,8)) THEN
+              WRITE (6,'('' Default is stored.'')')
+           ELSE
+              WRITE (6,'('' Default is not stored.'')')
+           END IF
+           CALL OTS$CVT_L_TI(FOLDER1_BBEXPIRE,BULL_PARAMETER,,,)
+           IF (FOLDER1_BBEXPIRE.GT.0) THEN
+              WRITE (6,'('' Default expiration for stored groups is ''
+     &         ,A,''.'')') BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+           ELSE IF (CLASS) THEN
+              WRITE (6,'('' Expiration is DEFAULT value.'')')
+           ELSE
+              WRITE (6,'('' Default expiration for stored groups is ''
+     &			 ,''14.'')')
+           END IF
+           CALL OTS$CVT_L_TI(F1_EXPIRE_LIMIT,BULL_PARAMETER,,,)
+           IF (F1_EXPIRE_LIMIT.GT.0) THEN
+              WRITE (6,'('' Default expiration limit is '',A,''.'')')
+     &                  BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+           ELSE IF (CLASS.AND.F1_EXPIRE_LIMIT.EQ.0) THEN 
+              WRITE (6,'('' Expiration limit is DEFAULT value.'')')
+           ELSE
+              WRITE (6,'('' There is no default expiration limit.'')')
+           END IF
+           IF (BTEST(FOLDER1_FLAG,0)) THEN
+              WRITE (6,'('' Private is set.'')')
+           END IF
+        ELSE IF (BTEST(FOLDER1_FLAG,9)) THEN
+	   FOLDER1_NAME = FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,' ')-1)
+           WRITE (6,'('' For news group '',A,'':'')') 
+     &			FOLDER1_NAME(:TRIM(FOLDER1_NAME))
+           WRITE (6,'('' Disable is set.'')')
+	ELSE
+	   FOLDER1_NAME = FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,' ')-1)
+           WRITE (6,'('' For news group '',A,'':'')') 
+     &			FOLDER1_NAME(:TRIM(FOLDER1_NAME))
+           IF (BTEST(FOLDER1_FLAG,8)) THEN
+              WRITE (6,'('' News group is stored.'')')
+              CALL OTS$CVT_L_TI(FOLDER1_BBEXPIRE,BULL_PARAMETER,,,)
+              IF (FOLDER1_BBEXPIRE.GT.0) THEN
+                 WRITE (6,'('' Expiration is '',A,''.'')')
+     &                  BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+              ELSE
+                 WRITE (6,'('' Expiration is DEFAULT value.'')')
+              END IF
+           ELSE
+              WRITE (6,'('' News group is not stored.'')')
+	   END IF
+           CALL OTS$CVT_L_TI(F1_EXPIRE_LIMIT,BULL_PARAMETER,,,)
+           IF (F1_EXPIRE_LIMIT.GT.0) THEN
+              WRITE (6,'('' Expiration limit is '',A,''.'')')
+     &                  BULL_PARAMETER(FIRST_ALPHA(BULL_PARAMETER):)
+           ELSE IF (F1_EXPIRE_LIMIT.EQ.0) THEN 
+              WRITE (6,'('' Expiration limit is DEFAULT value.'')')
+           ELSE
+              WRITE (6,'('' There is no expiration limit.'')')
+           END IF
+	   IF (BTEST(FOLDER1_FLAG,1)) THEN
+	      WRITE (6,'('' DUMP has been set.'')')
+	   END IF
+           IF (BTEST(FOLDER1_FLAG,0)) THEN
+              WRITE (6,'('' Private is set.'')')
+           END IF
+           NOTIFY_FLAG_NEWS = .FALSE.
+           SET_FLAG_NEWS = .FALSE.
+	   BRIEF_FLAG_NEWS = .FALSE.
+ 	   CALL OPEN_BULLINF_SHARED
+           DO WHILE (REC_LOCK(IER1))
+              READ (9,KEY='*DEFAULT',IOSTAT=IER1) TEMP_USER,INF_REC
+       	   END DO
+	   IF (IER1.EQ.0) THEN
+	      I = 1
+              DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	         I = I + 1
+       	      END DO
+	      IF (I.LE.FOLDER_MAX-1) THEN
+	         NOTIFY_FLAG_NEWS = BTEST(INF_REC2(2,I),13)
+	         SET_FLAG_NEWS = BTEST(INF_REC2(2,I),14)
+	         BRIEF_FLAG_NEWS = BTEST(INF_REC2(2,I),15)
+		 WRITE (6,'('' This is a default news group.'')')
+              ELSE
+	         IER1 = 2
+	      END IF
+           END IF
+           NOTIFY_PERM_FLAG_NEWS = .FALSE.
+           SET_PERM_FLAG_NEWS = .FALSE.
+	   BRIEF_PERM_FLAG_NEWS = .FALSE.
+           DO WHILE (REC_LOCK(IER2))
+              READ (9,KEY='*PERM',IOSTAT=IER2) TEMP_USER,INF_REC
+       	   END DO
+	   IF (IER2.EQ.0) THEN
+	      I = 1
+              DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.I.LE.FOLDER_MAX-1)
+	         I = I + 1
+       	      END DO
+	      IF (I.LE.FOLDER_MAX-1) THEN
+	         NOTIFY_PERM_FLAG_NEWS = BTEST(INF_REC2(2,I),13)
+	         SET_PERM_FLAG_NEWS = BTEST(INF_REC2(2,I),14)
+	         BRIEF_PERM_FLAG_NEWS = BTEST(INF_REC2(2,I),15)
+		 WRITE (6,'('' This is a permanent news group.'')')
+	      END IF
+           END IF
+	   PERM = .FALSE.
+	   IF (SET_FLAG_NEWS) THEN
+	      IF (BRIEF_FLAG_NEWS) THEN
+	         IF (SET_PERM_FLAG_NEWS.AND.BRIEF_PERM_FLAG_NEWS) THEN
+	            PERM = .TRUE.
+		    WRITE (6,'('' Default is BRIEF, which is permanent.'')')
+		 ELSE
+		    WRITE (6,'('' Default is BRIEF.'')')
+		 END IF
+	      ELSE
+	        IF (SET_PERM_FLAG_NEWS.AND..NOT.BRIEF_PERM_FLAG_NEWS) THEN
+	           PERM = .TRUE.
+		   WRITE (6,'('' Default is READNEW, which is permanent.'')')
+		ELSE
+		   WRITE (6,'('' Default is READNEW.'')')
+		END IF
+	      END IF
+	   ELSE IF (BRIEF_FLAG_NEWS) THEN
+	      IF (.NOT.SET_PERM_FLAG_NEWS.AND.BRIEF_PERM_FLAG_NEWS) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is SHOWNEW, which is permanent.'')')
+	      ELSE
+		 WRITE (6,'('' Default is SHOWNEW.'')')
+    	      END IF
+	   END IF
+	   IF (.NOT.PERM) THEN
+	    IF (SET_PERM_FLAG_NEWS.AND.BRIEF_PERM_FLAG_NEWS) THEN
+	      	WRITE (6,'('' BRIEF is the permanent setting.'')')
+	    ELSE IF (SET_PERM_FLAG_NEWS.AND..NOT.BRIEF_PERM_FLAG_NEWS) THEN
+		WRITE (6,'('' READNEW is the permanent setting.'')')
+	    ELSE IF (BRIEF_PERM_FLAG_NEWS.AND..NOT.SET_PERM_FLAG_NEWS) THEN
+		WRITE (6,'('' SHOWNEW is the permanent setting.'')')
+	    END IF
+	   END IF
+	   IF (NOTIFY_FLAG_NEWS) THEN
+	      IF (NOTIFY_PERM_FLAG_NEWS) THEN
+		 WRITE (6,'('' Default is NOTIFY, which is permanent.'')')
+	      ELSE IF (IER1.EQ.0) THEN
+		 WRITE (6,'('' Default is NOTIFY.'')')
+	      END IF
+	   ELSE IF (NOTIFY_PERM_FLAG_NEWS) THEN
+	      WRITE (6,'('' NOTIFY is permanent.'')')
+	   ELSE IF (IER1.EQ.0) THEN
+ 	      WRITE (6,'('' Default is NONOTIFY.'')')
+	   END IF
+	   CALL CLOSE_BULLINF
+ 	END IF
+
+	IF (CLI$PRESENT('FULL').AND.BTEST(FOLDER1_FLAG,0)) THEN
+	   CALL CHKACL(NEWS_ACCESS(FOLDER1_DESCRIP),IER)
+	   IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.IER) THEN
+	      IF (SETPRV_PRIV()) THEN
+	         READ_ACCESS = 1
+		 WRITE_ACCESS = 1
+	      ELSE
+	        CALL CHECK_ACCESS(NEWS_ACCESS(FOLDER1_DESCRIP),
+     &		   USERNAME,READ_ACCESS,WRITE_ACCESS)
+	      END IF
+	      IF (WRITE_ACCESS) CALL SHOWACL(NEWS_ACCESS(FOLDER1_DESCRIP))
+	   ELSE IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	      WRITE (6,'('' Access is not limited.'')')
+	   END IF
+	END IF
+
+        IF (EXPIRE.LT.0.AND.LIMIT.LT.-1.AND..NOT.FLAG.AND.
+     &		(.NOT.CLASS.OR.NEWCLASS.EQ.0)) THEN 
+	   CALL CLOSE_BULLNEWS
+	   RETURN
+	END IF
+
+ 	IF (CLASS.AND.(ALL.OR.FLAG)) THEN
+           WRITE (6,'('' Modifying news groups...'')')
+	   FOLDER_SAVE = FOLDER
+	   CALL LOWERCASE(GROUP)
+           CALL READ_FOLDER_FILE_KEYNAME_TEMP(GROUP(:LG-1),IER)
+	   IF (IER.NE.0.OR.GROUP(:LG-1).NE.FOLDER1) THEN
+	      CALL READ_FOLDER_FILE_KEYNAMEGE_TEMP(GROUP(:LG),IER)
+	   END IF
+	   FOUND = .FALSE.
+	   MODALL = INDEX(GROUP,'.').NE.LG
+           DO WHILE (IER.EQ.0.AND.(GROUP(:LG).EQ.FOLDER1(:LG).OR.
+     &			GROUP(:LG).EQ.FOLDER1(:TRIM(FOLDER1))//'.'))
+ 	      FOUND = .TRUE.
+	      IF (STORED.EQ.2.AND.BTEST(FOLDER1_FLAG,8)) THEN 
+	         CALL CLOSE_BULLNEWS
+                 FOLDER_NUMBER = -1
+                 CALL SELECT_FOLDER(.FALSE.,IER)
+	         IF (IER) THEN
+                    CALL OPEN_BULLDIR
+                    CALL CLOSE_BULLDIR_DELETE
+	         END IF
+	         CALL OPEN_BULLNEWS_SHARED
+           	 CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+                 F1_LAST = 0
+                 F1_COUNT = 0
+		 F1_START = 0
+		 F1_NBULL = 0
+	         FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,8) 
+	         FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,13)
+	      ELSE IF (STORED.EQ.1.AND..NOT.BTEST(FOLDER1_FLAG,8)) THEN
+	         F1_LAST = 0
+                 F1_COUNT = 0
+		 F1_START = 0
+		 F1_NBULL = 0
+		 NEWS_F1_FIRST = 0
+                 NEWS_F1_END = 0
+	         FOLDER1_FLAG = IBSET(FOLDER1_FLAG,8)
+              END IF
+              IF (EXPIRE.GE.0) FOLDER1_BBEXPIRE = 0
+              IF (EXPIRE.GE.0.AND.MODALL) FOLDER1_BBEXPIRE = EXPIRE
+              IF (LIMIT.GE.0) F1_EXPIRE_LIMIT = 0
+              IF (LIMIT.GE.0.AND.MODALL) F1_EXPIRE_LIMIT = LIMIT
+	      IF (ENABLE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,9)
+	      IF (DISABLE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,9)
+	      IF (PRIVATE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,0)
+	      IF (NOPRIVATE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+              CALL REWRITE_FOLDER_FILE_TEMP(IER)
+              CALL READ_FOLDER_FILE_KEYNAMEGT_TEMP(FOLDER1,IER)
+           END DO
+	   IF (.NOT.FOUND) THEN
+	      WRITE (6,'('' ERROR: No news groups match class name.'')') 
+	      WRITE (6,'('' ERROR: Class has been removed.'')') 
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL STR$UPCASE(GROUP,GROUP)
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(GROUP(:LG),IER)
+              DELETE (7) 
+	      CALL CLOSE_BULLNEWS
+	      OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &					STATUS='OLD',IOSTAT=IER)
+	      CLOSE (UNIT=3,DISPOSE='DELETE')
+	   END IF
+	   IF (FOLDER_SAVE.NE.FOLDER) THEN 
+              FOLDER_NUMBER = -1
+	      FOLDER1 = FOLDER_SAVE
+              CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (.NOT.IER) THEN 
+	         FOLDER_NUMBER = 0
+	         CALL SELECT_FOLDER(.FALSE.,IER)
+                 WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &              FOLDER(:TRIM(FOLDER))
+	      END IF
+	      RETURN
+           END IF
+ 	ELSE IF (DEFAULT.AND.(ALL.OR.FLAG)) THEN
+           WRITE (6,'('' Modifying news groups.'',
+     &			''  This will take a while...'')')
+	   IER = 0
+	   DO WHILE (IER.EQ.0)
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+              IF (EXPIRE.GE.0) FOLDER1_BBEXPIRE = 0
+              IF (LIMIT.GE.0) F1_EXPIRE_LIMIT = 0
+	      IF ((STORED.EQ.1.AND..NOT.BTEST(FOLDER1_FLAG,8)).OR.
+     &		  (STORED.EQ.2.AND.BTEST(FOLDER1_FLAG,8))) THEN 
+                 F1_LAST = 0
+                 F1_COUNT = 0
+		 F1_START = 0
+		 F1_NBULL = 0
+		 NEWS_F1_FIRST = 0
+                 NEWS_F1_END = 0
+              END IF
+	      IF (STORED.EQ.1) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,8)
+	      IF (STORED.EQ.2) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,8)
+	      IF (STORED.EQ.2) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,13)
+	      IF (ENABLE) FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,9)
+	      IF (DISABLE) FOLDER1_FLAG = IBSET(FOLDER1_FLAG,9)
+	      CALL REWRITE_FOLDER_FILE_TEMP(IER)
+	   END DO	   
+	END IF
+
+	FOLDER_NUMBER = -1
+	FOLDER1 = FOLDER
+        CALL SELECT_FOLDER(.FALSE.,IER)
+	IF (.NOT.IER) THEN 
+	   FOLDER_NUMBER = 0
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+           WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &        FOLDER(:TRIM(FOLDER))
+	END IF
+
+	CALL CLOSE_BULLNEWS
+
+        RETURN
+        END
+
+
+
+
+	SUBROUTINE INCLUDE(EXCLUDE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+ 	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER TODAY*24
+
+	DIMENSION BTIM(2)
+
+	ALL = CLI$PRESENT('ALL')
+	FULL = CLI$PRESENT('FULL')
+	IF (.NOT.CLI$GET_VALUE('P1',INPUT,LEN_P).AND..NOT.ALL) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	      WRITE(6,'('' ERROR: You have not read any message.'')')
+	      RETURN			! And return
+	   END IF
+
+	   CALL OPEN_BULLDIR_SHARED
+
+	   BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,1)
+	   CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+	   BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+
+       	   IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	      WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      CALL CLOSE_BULLDIR		! If not, then error out
+	      RETURN
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED	! Open BULLETIN file
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (CLI$PRESENT('SUBJECT')) THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      ELSE
+	         INPUT = INPUT(7:) 
+	         IF (INDEX(INPUT,'%"').GT.0) THEN
+	            INPUT = INPUT(INDEX(INPUT,'%"')+2:ILEN-1)
+	         END IF
+	      END IF
+	   ELSE
+	      INPUT = FROM
+	   END IF
+	   IF (CLI$PRESENT('SUBJECT')) THEN
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	         INPUT = INPUT(7:)
+	      ELSE
+		 INPUT = DESCRIP
+	      END IF
+	   END IF
+	   LEN_P = TRIM(INPUT)
+	   CALL CLOSE_BULLFIL
+	END IF
+
+	SUB = CLI$PRESENT('SUBJECT')
+	DISABLE = CLI$PRESENT('DISABLE')
+	EXC = 0
+
+	GO TO 5
+
+	ENTRY INCLUDE_SUBJECT(EXCLUDE)
+
+	IF (REMOTE_SET.GE.3.AND.NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) RETURN
+
+	LEN_P = TRIM(INPUT)
+	ALL = .FALSE.
+	DISABLE = .FALSE.
+	SUB = .TRUE.
+	EXC = -1
+
+5	IF (SUB) THEN
+	   IF (DISABLE) THEN
+	      IF (STREQ(INPUT(:3),'RE:')) INPUT = INPUT(5:)
+	      INPUT = INPUT(:MIN(LEN_P,LEN(DESCRIP)))
+	      LEN_P = TRIM(INPUT)
+	   END IF
+	   INPUT = 'SUBJECT:'//INPUT
+	   LEN_P = LEN_P + 8
+	ELSE
+	   INPUT = 'FROM:'//INPUT
+	   LEN_P = LEN_P + 5
+	END IF
+
+	IF (EXCLUDE) THEN
+	   INPUT = ':exclude:'//INPUT
+	   LEN_P = LEN_P + 9
+	ELSE
+	   INPUT = ':include:'//INPUT
+	   LEN_P = LEN_P + 9
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	L_TODAY = TRIM(TODAY)
+
+	FLEN = TRIM(FOLDER_NAME)
+	INPUT = FOLDER_NAME(:FLEN)//INPUT
+    	ILEN = FLEN + LEN_P
+
+	IF (EXC.EQ.0) THEN
+	   EXC = -1
+	   IER = CLI$GET_VALUE('LIMIT',BULL_PARAMETER,LEN_P)
+	   IF (IER) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER,IOSTAT=IER) EXC
+	      IF (EXC.LT.0.OR.EXC.GT.999.OR.IER.NE.0) THEN 
+	         WRITE(6,'('' ERROR: Valid limit is 0-999.'')')
+	         RETURN
+	      END IF
+	   END IF
+	END IF
+
+	CHECK_ONLY = .FALSE.
+
+	GO TO 100
+
+	ENTRY CHECK_EXCLUDES
+
+	CHECK_ONLY = .TRUE.
+	DISABLE = .TRUE.
+	LEN_P = 0
+	INPUT = ' '
+	ILEN = 1
+
+100	IER = SYS_TRNLNM('BULL_USER_CUSTOM',BULL_PARAMETER)
+	IF (.NOT.IER) BULL_PARAMETER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	CALL DISABLE_PRIVS
+
+	OPEN(UNIT=3,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER1,RECL=INPUT_LENGTH)
+
+	OPEN(UNIT=4,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    DISPOSE='DELETE',CARRIAGECONTROL='LIST',STATUS='NEW',
+     &	    SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	CALL ENABLE_PRIVS
+
+	IF (IER.NE.0) THEN
+	   CLOSE (UNIT=3)
+	   WRITE(6,'('' ERROR: Error in opening new custom file.'')')
+	   RETURN
+	END IF
+
+	IF (IER1.NE.0) THEN
+	   IF (.NOT.DISABLE.AND.LEN_P.GT.0) THEN 
+	      CALL ADD_EXCL(INPUT,ILEN,EXC)
+	      WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	   CLOSE (UNIT=4,DISPOSE='SAVE')
+	   RETURN
+	END IF
+
+	IER = 0
+	CONVERT = .FALSE.
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER) OLEN,OLD_BUFFER
+	   I = STRFIND(OLD_BUFFER,':RE: ')
+	   IF (IER.EQ.0) THEN
+	      IF (INDEX(OLD_BUFFER(FLEN+2:),'defaults').EQ.1.AND.FULL
+     &		.AND.INPUT(:FLEN).EQ.OLD_BUFFER(:MIN(FLEN,OLEN))) THEN
+		 I = INDEX(OLD_BUFFER,':kill')
+		 IF (DISABLE.AND.I.GT.0) THEN
+		    IF (I.GT.FLEN-1.OR.OLEN.GT.I+4) THEN
+		       OLD_BUFFER = OLD_BUFFER(:I-1)//OLD_BUFFER(I+5:)
+		       WRITE (4,'(A)',IOSTAT=IER) OLD_BUFFER(:OLEN-5)
+		    END IF
+	         ELSE IF (.NOT.DISABLE.AND.I.EQ.0) THEN
+		    OLD_BUFFER = OLD_BUFFER(:OLEN)//':kill'
+		    WRITE (4,'(A)',IOSTAT=IER) OLD_BUFFER(:OLEN+5)
+		    FULL = .FALSE.
+	         END IF
+	      ELSE IF ((STREQ(OLD_BUFFER(:ILEN),INPUT(:ILEN)).AND.
+     &		OLD_BUFFER(ILEN+1:ILEN+1).EQ.':').OR.
+     &		(OLEN.LT.ILEN.AND.INPUT(OLEN+1:OLEN+1).EQ.':'.AND.
+     &		 STREQ(OLD_BUFFER(:OLEN),INPUT(:OLEN))).OR.
+     &	         (DISABLE.AND.I.GT.0.AND.
+     &	         ((STREQ(OLD_BUFFER(:I)//OLD_BUFFER(I+5:MAX(I+5,ILEN+4)),
+     &		   INPUT(:ILEN)).AND.OLD_BUFFER(ILEN+5:ILEN+5).EQ.':').OR.
+     &		   (OLEN.LT.ILEN.AND.INPUT(OLEN+1:OLEN+1).EQ.':'.AND.
+     &		    STREQ(OLD_BUFFER(:I)//OLD_BUFFER(I+5:OLEN),
+     &		    INPUT(:OLEN)))))) THEN 
+	         CONTINUE
+ 	      ELSE IF (.NOT.(ALL.AND.STREQ(INPUT(:FLEN+8),
+     &		OLD_BUFFER(:MIN(FLEN+8,OLEN))))) THEN
+		 IER2 = OLD_BUFFER(:1).EQ.':'.OR.
+     &			INDEX(OLD_BUFFER,':defaults:').GT.0
+		 IF (.NOT.IER2) THEN
+		    CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC1,BLIMIT,BDATE,IER1)
+		    IF (IER1) IER2 = COMPARE_DATE(OLD_BUFFER(BDATE:OLEN-1)
+     &		    		     ,' ').GT.-EXC1
+		    CONVERT = .NOT.IER1
+		 END IF
+		 IF (.NOT.IER1.OR.EXC1.EQ.0.OR.IER2)
+     &	            WRITE (4,'(A)',IOSTAT=IER) OLD_BUFFER(:OLEN)
+	      END IF
+	   END IF
+	END DO
+
+	IF (.NOT.DISABLE) THEN
+	   IF (FULL) THEN
+	      WRITE (4,'(A)',IOSTAT=IER) FOLDER_NAME(:FLEN)//':defaults:kill'
+	   ELSE
+	      CALL ADD_EXCL(INPUT,ILEN,EXC)
+	      WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	END IF
+
+	IF (CONVERT) THEN 
+	   WRITE (6,'('' NOTE: See help on the new SET EXLIMIT command.'')')
+	END IF
+
+	CLOSE (UNIT=4,DISPOSE='SAVE')
+	CLOSE (UNIT=3,DISPOSE='DELETE')
+
+	CALL LIB$RENAME_FILE(BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &			     BULL_PARAMETER(:TRIM(BULL_PARAMETER))//';1')
+    
+	IF (.NOT.CHECK_ONLY) CALL CHECK_CUSTOM
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_EXCLUDE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+	DATA SCRATCH_B1/0/,NINCLUDE/0/,EXC_CHANGED/.FALSE./
+
+	CHARACTER TODAY*24
+
+	DIMENSION BTIM(2)
+
+	IF (.NOT.EXC_CHANGED) RETURN
+	EXC_CHANGED = .FALSE.
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	L_TODAY = TRIM(TODAY)
+
+	IER = SYS_TRNLNM('BULL_USER_CUSTOM',BULL_PARAMETER)
+	IF (.NOT.IER) BULL_PARAMETER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	CALL DISABLE_PRIVS
+
+	OPEN(UNIT=3,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER1,RECL=INPUT_LENGTH)
+
+	OPEN(UNIT=4,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    DISPOSE='DELETE',CARRIAGECONTROL='LIST',STATUS='NEW',
+     &	    SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	CALL ENABLE_PRIVS
+
+	IF (IER.NE.0) THEN
+	   CLOSE (UNIT=3)
+	   WRITE(6,'('' ERROR: Error in opening new custom file.'')')
+	   RETURN
+	END IF
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	   IF (.NOT.(IER.EQ.0.AND.FOLDER_NAME(:TRIM(FOLDER_NAME))//':'.EQ.
+     &		INPUT(:MIN(TRIM(FOLDER_NAME)+1,ILEN)).AND.INPUT(:1).NE.':'
+     & 		.AND.INDEX(INPUT,':defaults:').EQ.0)) THEN 
+	      IF (IER.EQ.0) WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	END DO
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+	DO I=1,NINCLUDE
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,INPUT)
+	   WRITE (4,'(A)',IOSTAT=IER) INPUT(:TRIM(INPUT))
+	END DO
+
+	CLOSE (UNIT=4,DISPOSE='SAVE')
+	CLOSE (UNIT=3,DISPOSE='DELETE')
+
+	CALL LIB$RENAME_FILE(BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &			     BULL_PARAMETER(:TRIM(BULL_PARAMETER))//';1')
+
+	IF (.NOT.CHECK_ONLY) CALL CHECK_CUSTOM
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_CUSTOM(PARAM)
+C
+C  SUBROUTINE SET_CUSTOM
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EXCLUDE_LIMIT/ EXCLUDE_LIMIT
+	DATA EXCLUDE_LIMIT /0/
+
+	CHARACTER*(*) PARAM
+
+	IER = SYS_TRNLNM('BULL_USER_CUSTOM',BULL_PARAMETER)
+	IF (.NOT.IER) BULL_PARAMETER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	CALL DISABLE_PRIVS
+
+	OPEN(UNIT=3,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER1,RECL=INPUT_LENGTH)
+
+	OPEN(UNIT=4,FILE=BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &	    DISPOSE='DELETE',CARRIAGECONTROL='LIST',STATUS='NEW',
+     &	    SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	CALL ENABLE_PRIVS
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Error in opening custom file.'')')
+	   RETURN
+	END IF
+
+	LENP = LEN(PARAM)
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	   IF (IER.EQ.0.AND.PARAM(:LENP).NE.INPUT(2:LENP+1)) THEN
+              WRITE (4,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	   END IF
+	END DO
+
+	IF (CLI$GET_VALUE('SET_PARAM2',INPUT,ILEN)) THEN
+	   WRITE (4,'(A)',IOSTAT=IER) ':'//PARAM(:LENP)//':'//INPUT(:ILEN)
+	END IF
+
+	IF (PARAM.EQ.'exclude_limit')
+     &		DECODE(ILEN,'(I<ILEN>)',INPUT(:ILEN)) EXCLUDE_LIMIT
+
+	CLOSE (UNIT=4,DISPOSE='SAVE')
+	CLOSE (UNIT=3,DISPOSE='DELETE')
+
+	CALL LIB$RENAME_FILE(BULL_PARAMETER(:TRIM(BULL_PARAMETER)),
+     &			     BULL_PARAMETER(:TRIM(BULL_PARAMETER))//';1')
+
+	CALL CHECK_CUSTOM
+
+        RETURN
+        END
+
+
+
+
+	SUBROUTINE CHECK_CUSTOM
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+
+	COMMON /FILE_DIRECTORY/ FILE_DIRECTORY
+	CHARACTER*64 FILE_DIRECTORY
+
+	COMMON /EXCLUDE_LIMIT/ EXCLUDE_LIMIT
+	DATA EXCLUDE_LIMIT /0/
+
+	DIMENSION BTIM(2)
+
+	FILE_DIRECTORY = ' '
+
+	IF (.NOT.BTEST(BULL_USER_CUSTOM,4)) THEN
+	   BULL_USER_CUSTOM = .FALSE.
+	ELSE
+	   BULL_USER_CUSTOM = .FALSE.
+	   BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,4)
+	END IF
+
+	IER = SYS_TRNLNM('BULL_USER_CUSTOM',OLD_BUFFER)
+	IF (.NOT.IER) OLD_BUFFER = 'SYS$LOGIN:BULL.CUSTOM'
+
+	OPEN(UNIT=17,FILE=OLD_BUFFER(:TRIM(OLD_BUFFER)),
+     &	    STATUS='OLD',SHARED,IOSTAT=IER,RECL=INPUT_LENGTH)
+
+	IF (IER.NE.0) RETURN
+
+	IF (SCRATCH_B1.NE.0) THEN		! Is queue empty?
+	   SCRATCH_B = SCRATCH_B1		! No, set queue pointer to head
+	ELSE					! Else if queue is empty
+	   CALL INIT_QUEUE(SCRATCH_B,OLD_BUFFER)
+	   SCRATCH_B1 = SCRATCH_B		! Init header pointer
+	END IF
+
+	NINCLUDE = 0
+	OLD_FORMAT = .FALSE.
+	FLEN = TRIM(FOLDER_NAME)
+	DO WHILE (IER.EQ.0)
+	   READ (17,'(Q,A)',IOSTAT=IER) OLEN,OLD_BUFFER
+	   IF (IER.EQ.0.AND.STREQ(FOLDER_NAME(:FLEN)//':',
+     &		OLD_BUFFER(:MIN(FLEN+1,OLEN)))) THEN
+	      BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+	      CALL LOWERCASE(OLD_BUFFER)
+	      IF (INDEX(OLD_BUFFER(FLEN+2:),'defaults')
+     &		.EQ.1) THEN
+		 IF (INDEX(OLD_BUFFER,':header').GT.0)
+     &		            BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,2)
+		 IF (INDEX(OLD_BUFFER,':kill').GT.0)
+     &		            BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,3)
+              ELSE
+	         BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,1)
+		 CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC,BLIMIT,BDATE,IER1)
+		 OLD_FORMAT = OLD_FORMAT.OR.(.NOT.IER1)
+		 IF (COMPARE_DATE(OLD_BUFFER(BDATE:OLEN-1),' ').GT.-EXC
+     &		     .OR.EXC.EQ.0) THEN
+	            CALL WRITE_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,OLD_BUFFER)
+	            NINCLUDE = NINCLUDE + 1
+		 ELSE
+		    EXC_CHANGED = .TRUE.
+		 END IF
+	      END IF
+	   ELSE IF (IER.EQ.0.AND.OLD_BUFFER(:1).EQ.':') THEN
+	      IF (INDEX(OLD_BUFFER,':header').GT.0)
+     &	                 BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,2)
+	      IF (INDEX(OLD_BUFFER,':kill').GT.0)
+     &	                 BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,3)
+	      IF (INDEX(OLD_BUFFER,':file_directory').GT.0)
+     &	                 FILE_DIRECTORY = OLD_BUFFER(17:)
+	      IF (INDEX(OLD_BUFFER,':exclude_limit').GT.0) THEN 
+	         DECODE(OLEN-15,'(I<OLEN-15>)',OLD_BUFFER(16:),IOSTAT=IER1)
+     &	                EXCLUDE_LIMIT
+	         EXCLUDE_LIMIT = MIN(999,EXCLUDE_LIMIT)
+	      END IF
+	   END IF
+	END DO
+
+	CLOSE (UNIT=17)
+	
+	IF (OLD_FORMAT) CALL CHECK_EXCLUDES
+
+        RETURN
+	END
+
+
+
+	
+	LOGICAL FUNCTION INCLUDE_MSG(STRING,STRING1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /DIRMODE/ DIRMODE
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+
+	CHARACTER*(*) STRING,STRING1
+	CHARACTER*132 ADDRESS
+
+	CHARACTER*12 EXFROM
+
+	INCLUDE_MSG = .TRUE.
+	IF (BTEST(BULL_USER_CUSTOM,4)) RETURN
+	IF (.NOT.BTEST(BULL_USER_CUSTOM,1)) RETURN
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+
+	FLEN = TRIM(FOLDER_NAME)
+
+	DO I=1,NINCLUDE
+	   OLD_SCRATCH_B = SCRATCH_B
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,OLD_BUFFER)
+	   OLEN = TRIM(OLD_BUFFER)
+	   IF (STREQ(FOLDER_NAME(:FLEN)//':',
+     &		OLD_BUFFER(:MIN(FLEN+1,OLEN)))) THEN
+	      CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC,BLIMIT,BDATE,IER1)
+	      IF (DIRMODE) BLIMIT = MIN(BLIMIT,FLEN+17+LEN(DESCRIP))
+	      MATCH = .FALSE.
+	      IF (STREQ(OLD_BUFFER(FLEN+10:FLEN+14),'FROM:')) THEN
+		 CALL GET_FROM(EXFROM,OLD_BUFFER(FLEN+15:),
+     &			       TRIM(OLD_BUFFER(FLEN+15:)))
+		 IF (STREQ(ADDRESS(STRING),ADDRESS(OLD_BUFFER(FLEN+15:
+     &		     TRIM(OLD_BUFFER(FLEN+15:BLIMIT))+FLEN+14))).OR.
+     &		     (DIRMODE.AND.STREQ(FROM,EXFROM))) MATCH = .TRUE.
+	      ELSE IF (STREQ(OLD_BUFFER(FLEN+10:FLEN+17),'SUBJECT:').AND.
+     &		  STRFIND(STRING1(:TRIM(STRING1)),
+     &		  	  OLD_BUFFER(FLEN+18:BLIMIT)).GT.0) THEN
+		 MATCH = .TRUE.
+	      END IF
+	      IF (MATCH) THEN
+		 CDATE = COMPARE_DATE(OLD_BUFFER(BDATE:OLEN-1),' ')
+		 IF (CDATE.GT.-EXC.OR.EXC.EQ.0) THEN
+		    IF (CDATE.NE.0.AND.EXC.NE.0) THEN 
+		       IF (OLD_BUFFER(BLIMIT+1:BLIMIT+1).EQ.':') EXC = -1
+		       CALL ADD_EXCL(OLD_BUFFER,BLIMIT,EXC)
+	               CALL WRITE_QUEUE(%VAL(OLD_SCRATCH_B),OLD_SCRATCH_B,
+     &				OLD_BUFFER)
+		       EXC_CHANGED = .TRUE.
+		    END IF
+	   	    IF (STREQ(OLD_BUFFER(FLEN+2:FLEN+8),'INCLUDE')) THEN
+		       SYSTEM = IBSET(SYSTEM,8)
+		    ELSE
+		       INCLUDE_MSG = .FALSE.
+		       SYSTEM = IBCLR(SYSTEM,8)
+		    END IF
+		 END IF
+	      END IF
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+	FUNCTION STRFIND(STRING,STRING1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) STRING,STRING1
+
+	L = LEN(STRING1)
+	DO I=0,LEN(STRING)-L
+	   J = 1
+	   DO WHILE (J.LE.L)
+	      DIFF = ABS(ICHAR(STRING(I+J:I+J))-ICHAR(STRING1(J:J)))
+	      IF (DIFF.NE.0.AND.(DIFF.NE.32.OR..NOT.ALPHA(STRING1(J:J))
+     &		  .OR..NOT.ALPHA(STRING(I+J:I+J)))) THEN
+		 J = L + 1
+	      ELSE IF (J.EQ.L) THEN
+		 STRFIND = I + 1
+		 RETURN
+	      ELSE
+	         J = J + 1
+	      END IF
+	   END DO
+	END DO
+
+	STRFIND = 0
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOW_EXCLUDE(TYPE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /SCRATCH_INCLUDE/ SCRATCH_B1,NINCLUDE,EXC_CHANGED
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	IF (.NOT.BTEST(BULL_USER_CUSTOM,1)) THEN
+	   IF (TYPE.EQ.0) WRITE (6,'('' There are no excludes.'')')
+	   IF (TYPE.EQ.1) WRITE (6,'('' There are no threads.'')')
+	   RETURN
+	END IF
+
+	SCRATCH_B = SCRATCH_B1			! Init queue pointer to header
+
+	FLEN = TRIM(FOLDER_NAME)
+
+	FOUND = .FALSE.
+
+	L = 1
+	DO I=1,NINCLUDE
+	   CALL READ_QUEUE(%VAL(SCRATCH_B),SCRATCH_B,OLD_BUFFER)
+	   OLEN = TRIM(OLD_BUFFER)
+	   IF (STREQ(FOLDER_NAME(:FLEN)//':',OLD_BUFFER(:MIN(FLEN+1,OLEN)))
+     &         .AND.((TYPE.EQ.1.AND.STREQ(OLD_BUFFER(FLEN+2:FLEN+8),
+     &	       'INCLUDE')).OR.(TYPE.EQ.0.AND.STREQ(
+     &	       OLD_BUFFER(FLEN+2:FLEN+8),'EXCLUDE')))) THEN
+	      IF (.NOT.FOUND) THEN
+	         IF (TYPE.EQ.0) WRITE (6,'(1X,A,$)') 'Excludes for '
+		 IF (TYPE.EQ.1) WRITE (6,'(1X,A,$)') 'Threads for '
+		 WRITE (6,'(A)') '+'//FOLDER_NAME(:FLEN)//':'
+	         FOUND = .TRUE.
+ 	      END IF
+	      CALL CHECK_EXCL(OLD_BUFFER,OLEN,EXC,BLIMIT,BDATE,IER1)
+	      IF (BLIMIT+5-FLEN.GT.PAGE_WIDTH.AND.L+2.GT.PAGE_LENGTH-1) THEN
+	         L = L + 2
+	      ELSE
+		 IF (L.EQ.0) THEN 
+	            WRITE (6,'(''+'',A,$)') OLD_BUFFER(FLEN+10:
+     &		      MIN(BLIMIT,PAGE_WIDTH+FLEN+9))
+		 ELSE
+	            WRITE (6,'(1X,A,$)') OLD_BUFFER(FLEN+10:
+     &		      MIN(BLIMIT,PAGE_WIDTH+FLEN+9))
+		 END IF
+		 IF (OLD_BUFFER(BDATE+1:BDATE+1).EQ.'-')
+     &		     OLD_BUFFER(BDATE:) = ' '//OLD_BUFFER(BDATE:)
+		 OUTLEN = MIN(BLIMIT,PAGE_WIDTH+FLEN+9)-FLEN-9
+		 IF (OUTLEN.GT.PAGE_WIDTH-16) THEN
+		    WRITE (6,'(1X,<PAGE_WIDTH-15>X,A,1X,I3)')
+     &		       OLD_BUFFER(BDATE:INDEX(OLD_BUFFER
+     &		       (BDATE:),':')+BDATE-2),EXC
+		    L = L + 2
+		 ELSE
+		    WRITE (6,'(''+'',<PAGE_WIDTH-15-OUTLEN>X,A,1X,I3)')
+     &		       OLD_BUFFER(BDATE:INDEX(OLD_BUFFER
+     &		       (BDATE:),':')+BDATE-2),EXC
+		    L = L + 1
+		 END IF
+	      END IF
+              IF (PAGING.AND.L.EQ.PAGE_LENGTH-1) THEN
+                 L = 0                        ! Reinitialize screen counter
+	         CALL LIB$PUT_OUTPUT(' ')
+		 CALL GET_INPUT_NOECHO_PROMPT(
+     &				INPUT(:1),'Press key to continue ... ')
+             	 IER = LIB$ERASE_PAGE(1,1)         ! Erase display
+	      END IF
+	   END IF
+	END DO
+
+	IF (.NOT.FOUND) THEN
+	   IF (TYPE.EQ.0) WRITE (6,'(1X,A,$)') 'No excludes found for '
+	   IF (TYPE.EQ.1) WRITE (6,'(1X,A,$)') 'No threads found for '
+	   WRITE (6,'(A)') '+'//FOLDER_NAME(:FLEN)//':'
+	END IF
+
+	RETURN
+	END
+
+
+
+        SUBROUTINE SET_NEWNAME
+
+        IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLUSER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+
+	CHARACTER*12 NEW,OLD
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: No privs to set a new name.'')')
+	   RETURN
+	END IF
+
+	CALL CLI$GET_VALUE('OLDNAME',OLD,LENO)
+	CALL CLI$GET_VALUE('NEWNAME',NEW,LENN)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	TEMP_USER = USERNAME
+        DO WHILE (REC_LOCK(IER))
+	   READ (4,IOSTAT=IER,KEYEQ=OLD) USER_ENTRY
+	END DO 
+
+	IF (IER.EQ.0) THEN
+	   USERNAME = NEW
+           DO WHILE (REC_LOCK(IER))
+	      READ (4,IOSTAT=IER,KEYEQ=NEW)
+	   END DO 
+	   IF (IER.NE.0) THEN
+	      WRITE (4,IOSTAT=IER) USER_ENTRY
+	   ELSE
+	      REWRITE (4,IOSTAT=IER) USER_ENTRY
+	   END IF	
+	END IF	
+
+	USERNAME = TEMP_USER
+        DO WHILE (REC_LOCK(IER1))
+	   READ (4,IOSTAT=IER1,KEYEQ=USERNAME) USER_ENTRY
+	END DO 
+
+	CALL CLOSE_BULLUSER
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Old name not found.'')') 
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLINF_SHARED
+
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=OLD,IOSTAT=IER) OLD,LAST
+	END DO 
+
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=NEW,IOSTAT=IER)
+	END DO 
+	IF (IER.NE.0) THEN
+	   WRITE (9,IOSTAT=IER) NEW,LAST
+	ELSE
+	   REWRITE (9,IOSTAT=IER) NEW,LAST
+	END IF	
+
+	OLD(LENO:LENO) = CHAR(128.OR.ICHAR(OLD(LENO:LENO)))
+	NEW(LENN:LENN) = CHAR(128.OR.ICHAR(NEW(LENN:LENN)))
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=OLD,IOSTAT=IER) OLD,LAST
+	END DO 
+	IF (IER.EQ.0) THEN
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.NE.0) THEN
+	      WRITE (9,IOSTAT=IER) NEW,LAST
+	   ELSE
+	      REWRITE (9,IOSTAT=IER) NEW,LAST
+	   END IF	
+	ELSE
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.EQ.0) DELETE (9)
+	END IF
+	OLD(LENO:LENO) = CHAR(127.AND.ICHAR(OLD(LENO:LENO)))
+	NEW(LENN:LENN) = CHAR(127.AND.ICHAR(NEW(LENN:LENN)))
+
+	OLD(LENO:LENO) = CHAR(128.OR.ICHAR(OLD(LENO:LENO)))
+	IF (LENO.GT.1) THEN
+	   OLD(LENO-1:LENO-1) = CHAR(128.OR.ICHAR(OLD(LENO-1:LENO-1)))
+	ELSE
+	   OLD(2:2) = CHAR(128.OR.ICHAR(OLD(2:2)))
+	END IF
+	NEW(LENN:LENN) = CHAR(128.OR.ICHAR(NEW(LENN:LENN)))
+	IF (LENN.GT.1) THEN
+	   NEW(LENN-1:LENN-1) = CHAR(128.OR.ICHAR(NEW(LENN-1:LENN-1)))
+	ELSE
+	   NEW(2:2) = CHAR(128.OR.ICHAR(NEW(2:2)))
+	END IF
+        DO WHILE (REC_LOCK(IER))
+	   READ (9,KEY=OLD,IOSTAT=IER) OLD,LAST
+	END DO 
+	IF (IER.EQ.0) THEN
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.NE.0) THEN
+	      WRITE (9,IOSTAT=IER) NEW,LAST
+	   ELSE
+	      REWRITE (9,IOSTAT=IER) NEW,LAST
+	   END IF	
+	ELSE
+           DO WHILE (REC_LOCK(IER))
+	      READ (9,KEY=NEW,IOSTAT=IER)
+	   END DO 
+	   IF (IER.EQ.0) DELETE (9)
+	END IF
+
+	CALL CLOSE_BULLINF
+
+        RETURN
+        END
+
+
+	SUBROUTINE CHECK_EXCL(BUFFER,L,EXC,BLIMIT,BDATE,IER)
+
+        IMPLICIT INTEGER (A-Z)
+
+	COMMON /EXCLUDE_LIMIT/ EXCLUDE_LIMIT
+
+        CHARACTER*(*) BUFFER
+
+	DIMENSION BTIM(2)
+
+	BLIMIT = L
+	BDATE = L+3
+
+	IER = BUFFER(L:L).EQ.':'
+	IF (IER) THEN
+	   I = LAST_INDEX(BUFFER(:L-1),':')
+	   IF (I.GT.0) THEN
+	      J = LAST_INDEX(BUFFER(:I-1),':')
+	      IF (J.GT.0) THEN
+		 IF (J.LT.I-1) THEN
+		    DECODE(I-J-1,'(I<I-J-1>)',BUFFER(J+1:I-1),IOSTAT=IER) EXC
+		    IER = IER.EQ.0
+		 ELSE
+		    EXC = EXCLUDE_LIMIT
+		 END IF
+		 IF (IER) BLIMIT = J - 1
+		 CALL STR$UPCASE(BUFFER(I+1:L-1),BUFFER(I+1:L-1))
+		 IF (IER) IER = SYS_BINTIM(BUFFER(I+1:L-1),BTIM)
+		 BDATE = I + 1
+	      END IF
+	   ELSE
+	      IER = .FALSE.
+	   END IF
+	END IF
+
+	IF (.NOT.IER) CALL ADD_EXCL(BUFFER,L,-1)
+
+	RETURN
+	END	
+
+
+
+	SUBROUTINE ADD_EXCL(BUFFER,L,EXC)
+
+        IMPLICIT INTEGER (A-Z)
+
+	DIMENSION BTIM(2)
+
+        CHARACTER*(*) BUFFER
+	
+	CHARACTER TODAY*24
+
+	IF (EXC.EQ.-1) THEN
+	   BUFFER = BUFFER(:L)//':'
+	ELSE
+	   BUFFER = BUFFER(:L)//':'
+	   WRITE (BUFFER(L+2:),'(I3)') EXC
+	   IF (BUFFER(L+2:L+2).EQ. ' ') BUFFER(L+2:) = BUFFER(L+3:)
+	   IF (BUFFER(L+2:L+2).EQ. ' ') BUFFER(L+2:) = BUFFER(L+3:)
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	IF (TODAY(1:1).EQ.' ') TODAY = TODAY(2:)
+	BUFFER = BUFFER(:TRIM(BUFFER))//':'//TODAY(:INDEX(TODAY,' ')-1)//':'
+
+	L = TRIM(BUFFER)
+
+	RETURN
+	END	
+
+
+
+
+	CHARACTER*(*) FUNCTION ADDRESS(INPUT)
+
+	IMPLICIT INTEGER (A - Z)
+
+	CHARACTER*(*) INPUT
+
+	ADDRESS = INPUT
+
+	IF (INDEX(INPUT,'@').EQ.0) RETURN
+
+	I = INDEX(INPUT,'<')
+	IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN ! Name may be of form
+	   ADDRESS = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+						! personal-name <net-name>
+	ELSE
+	   ADDRESS = INPUT(:MINGT0(TRIM(INPUT),INDEX(INPUT,' ')-1))
+	   IF (INDEX(ADDRESS,'(').GT.0)
+     &	       ADDRESS = ADDRESS(:INDEX(ADDRESS,'(')-1)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SEND_MAIL
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER CRLF = CHAR(13)//CHAR(10)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	C = 0
+	DO WHILE (LIB$FIND_FILE(FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &			//'*.SMTP',INPUT,C))
+	   OPEN (UNIT=8,FILE=INPUT(:TRIM(INPUT)),IOSTAT=IER,RECL=256)
+	   IF (IER.NE.0) GOTO 30
+	   IF (.NOT.SMTP_CONNECT()) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'220') GOTO 10
+	   DO I=1,3
+	      READ (8,'(Q,A)',IOSTAT=IER) L,INPUT
+	      IF (IER.NE.0) GOTO 10
+	      IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) GOTO 10
+	      IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	      IF (INPUT(:3).NE.'250') GOTO 10
+	   END DO
+	   READ (8,'(Q,A)',IOSTAT=IER) L,INPUT
+	   IF (IER.NE.0) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (INPUT(:3).NE.'354') GOTO 10
+	   DO WHILE (IER.EQ.0)
+	      READ (8,'(Q,A)',IOSTAT=IER) L,INPUT
+	      IF (IER.EQ.0) THEN
+	         IF (.NOT.SMTP_WRITE_PACKET(INPUT(:L)//CRLF)) GOTO 10
+	      END IF
+	   END DO
+	   IF (.NOT.SMTP_WRITE_PACKET('.'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   IF (.NOT.SMTP_WRITE_PACKET('QUIT'//CRLF)) GOTO 10
+	   IF (SMTP_READ_PACKET(INPUT).EQ.0) GOTO 10
+	   CLOSE (UNIT=8,STATUS='DELETE')
+	   GOTO 20
+10	   CLOSE (UNIT=8)
+20	   CALL SMTP_DISCONNECT()
+30	   CONTINUE
+	END DO
+
+	CALL EXIT
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin2.for b/decus/vmslt98a/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..0bf191c119fc9bdb5ffefc480d3dfe24aa4e85df
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin2.for
@@ -0,0 +1,2675 @@
+C
+C  BULLETIN2.FOR, Version 3/10/97
+C  Purpose: Contains subroutines for the bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE SET_BBOARD(BBOARD)
+C
+C  SUBROUTINE SET_BBOARD
+C
+C  FUNCTION: Set username for BBOARD for selected folder.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($UAIDEF)'
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER EXPIRE*4,INPUT_BBOARD*12,TODAY*24,RESPONSE*4
+
+	IF (TRIM(BBOARD_DIRECTORY).EQ.0) THEN
+	 WRITE(6,'('' ERROR: System programmer has disabled BBOARD.'')')
+	 RETURN
+	END IF
+
+	IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	   IF (FOLDER_BBOARD(:2).EQ.'::') THEN
+	      WRITE (6,'(
+     &		'' ERROR: Cannot set BBOARD for remote folder.'')')
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   END IF
+
+	   IF (BBOARD) THEN
+	      IER = CLI$GET_VALUE('BB_USERNAME',INPUT_BBOARD,INPUT_LEN)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+		 CALL GET_UAF
+     &		   (INPUT_BBOARD,USERB,GROUPB,ACCOUNTB,FLAGS,IER1)
+		 CALL CLOSE_BULLFOLDER
+	         IF (IER1.AND..NOT.BTEST(FLAGS,UAI$V_DISACNT)) THEN ! DISUSER?
+	            WRITE (6,'('' ERROR: '',A,
+     &			'' account needs DISUSER flag set.'')')
+     &			INPUT_BBOARD(:INPUT_LEN)
+		    RETURN
+		 ELSE IF (IER1.AND.BTEST(USERB,31)) THEN
+		    WRITE (6,'('' ERROR: User number of UIC cannot '',
+     &				''be greater than 7777777777.'')')
+		    RETURN
+		 END IF
+		 CALL OPEN_BULLFOLDER
+		 CALL READ_FOLDER_FILE_TEMP(IER)
+		 DO WHILE ((FOLDER1_BBOARD.NE.INPUT_BBOARD.OR.
+     &		     FOLDER1_NUMBER.EQ.FOLDER_NUMBER).AND.IER.EQ.0)
+		   CALL READ_FOLDER_FILE_TEMP(IER)
+	         END DO
+		 IF (FOLDER1_BBOARD.EQ.INPUT_BBOARD.AND.
+     &		      FOLDER1_NUMBER.NE.FOLDER_NUMBER) THEN
+		    WRITE (6,'('' WARNING: Account used by other folder.'',
+     &		     '' If you specify the same account,'')')
+		    WRITE (6,'('' you must specify the address'',
+     &		     '' of the mailing list in the folder description.'')')
+		    CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &                 'Do you still want to make this change? ')
+		    IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+		       CALL CLOSE_BULLFOLDER
+		       WRITE (6,'('' Folder was not modified.'')')
+		       RETURN
+		    END IF
+		 END IF
+		 IF (.NOT.IER1) THEN
+		    CALL CLOSE_BULLFOLDER
+		    WRITE (6,'('' WARNING: '',A,'' account not in SYSUAF'',
+     &		       '' file.'')') INPUT_BBOARD(:INPUT_LEN)
+		    CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &                 'Is the name a mail forwarding entry? '//
+     &		       '(Y/N with N as default): ')
+		    IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+		       WRITE (6,'('' Folder was not modified.'')')
+		       RETURN
+		    END IF
+		    CALL OPEN_BULLFOLDER
+		    USERB = 1		! Fake userb/groupb, as old method of
+		    GROUPB = 1		! indicating /SPECIAL used [0,0]
+		 END IF
+		 GROUPB1 = GROUPB
+		 USERB1 = USERB
+		 ACCOUNTB1 = ACCOUNTB
+		 CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+		 GROUPB = GROUPB1
+		 USERB = USERB1
+		 ACCOUNTB = ACCOUNTB1
+		 FOLDER_BBOARD = INPUT_BBOARD
+		 CALL OPEN_BULLUSER
+		 CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+		 CALL READ_USER_FILE_HEADER(IER)
+		 CALL SYS_BINTIM(TODAY,BBOARD_BTIM)
+		 REWRITE (4) USER_HEADER
+		 CALL CLOSE_BULLUSER
+		 IF (CLI$PRESENT('SPECIAL')) THEN	! SPECIAL specified?
+		    USERB = IBSET(USERB,31)	! Set bit to show /SPECIAL
+		    IF (CLI$PRESENT('VMSMAIL')) THEN
+		       GROUPB = IBSET(GROUPB,31)   ! Set bit to show /VMSMAIL
+		    END IF
+		 END IF
+	      ELSE IF (CLI$PRESENT('SPECIAL')) THEN
+	         USERB = IBSET(0,31)		! Set top bit to show /SPECIAL
+	         GROUPB = 0
+	         DO I=1,LEN(FOLDER_BBOARD)
+		    FOLDER_BBOARD(I:I) = ' '
+	         END DO
+	      ELSE IF (FOLDER_BBOARD(:4).EQ.'NONE') THEN
+	         WRITE (6,'('' ERROR: No BBOARD specified for folder.'')')
+	      END IF
+
+	      IER = CLI$GET_VALUE('EXPIRATION',EXPIRE,EX_LEN)
+	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
+	         IF (EX_LEN.GT.3) EX_LEN = 3
+	         READ (EXPIRE,'(I<EX_LEN>)') TEMP
+		 IF (TEMP.GT.BBEXPIRE_LIMIT.AND..NOT.SETPRV_PRIV()) THEN
+		    WRITE (6,'('' ERROR: Expiration cannot be > '',
+     &			I3,'' days.'')') BBEXPIRE_LIMIT
+		    CALL CLOSE_BULLFOLDER
+		    RETURN
+		 ELSE IF (TEMP.LE.0) THEN
+		    WRITE (6,'('' ERROR: Expiration must be > 0.'')')
+		    CALL CLOSE_BULLFOLDER
+		    RETURN
+		 ELSE
+		    FOLDER_BBEXPIRE = TEMP
+		 END IF
+	      ELSE IF (.NOT.CLI$PRESENT('EXPIRATION')) THEN
+		 FOLDER_BBEXPIRE = -1
+	      END IF
+	   ELSE
+	      FOLDER_BBOARD = 'NONE'
+	   END IF
+
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLFOLDER
+	   WRITE (6,'('' BBOARD has been modified for folder.'')')
+	ELSE
+	   WRITE (6,'('' You are not authorized to modify BBOARD.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+
+	SUBROUTINE SET_SYSTEM(SYSTEM_SET)
+C
+C  SUBROUTINE SET_SYSTEM
+C
+C  FUNCTION: Set SYSTEM specification for selected folder.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	IF (FOLDER_NUMBER.LT.0.OR.FOLDER_NUMBER.GE.1000) THEN
+	   WRITE (6,'('' ERROR: Cannot modify for remote folder.'')')
+	ELSE IF (SETPRV_PRIV()) THEN
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   IF (SYSTEM_SET) THEN
+	      FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	      WRITE (6,'('' SYSTEM designation has been set.'')')
+	   ELSE
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,2)
+	      WRITE (6,'('' SYSTEM designation has been removed.'')')
+	   END IF
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL MODIFY_SYSTEM_LIST(0)
+	   CALL CLOSE_BULLFOLDER
+	   CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	ELSE
+	   WRITE (6,'('' You are not authorized to modify SYSTEM.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE MODIFY_SYSTEM_LIST(FILE_OPENED)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	INTEGER SHUTDOWN_BTIM(FLONG),VERSION(FLONG)
+
+	CHARACTER UPDATE*12,UPTIME*8
+
+	INTEGER UP_BTIM(2)
+
+	IF (.NOT.FILE_OPENED) CALL OPEN_BULLUSER
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*SYSTEM',IOSTAT=IER) 
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,VERSION,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END DO
+
+	IF (IER.NE.0.OR.VERSION(1).NE.168) THEN
+	   DO I=1,FLONG
+	      SYSTEM_FLAG(I) = 0
+	      SHUTDOWN_FLAG(I) = 0
+	   END DO
+	   CALL SET2(SYSTEM_FLAG,0)
+	   CALL LIB$SYS_TRNLOG('SYS$NODE',,NODENAME)
+	   NODENAME = NODENAME(2:INDEX(NODENAME,':')-1)
+	   SHUTDOWN_BTIM(1) = 0
+	   SHUTDOWN_BTIM(2) = 0
+	   NODE_NUMBER = 0
+	   NODE_AREA = 0
+	   IF (IER.EQ.0) THEN
+	      DO WHILE (TEMP_USER(:7).EQ.'*SYSTEM'.AND.IER.EQ.0)
+	         DELETE (UNIT=4)
+	         DO WHILE (REC_LOCK(IER))
+	           READ (4,IOSTAT=IER) TEMP_USER
+		 END DO
+	      END DO
+	      IER = 2
+	   ELSE
+	      VERSION(1) = 168
+	   END IF
+	END IF
+
+	IF (VERSION(1).NE.168) THEN
+	   CALL CLOSE_BULLFOLDER
+	   CALL OPEN_BULLFOLDER
+	   NODE_AREA = 0
+	   DO I=1,FLONG
+	      SYSTEM_FLAG(I) = 0
+	   END DO
+	   IER1 = 0
+	   DO WHILE (IER1.EQ.0)
+	      CALL READ_FOLDER_FILE_TEMP(IER1)
+	      IF (BTEST(FOLDER1_FLAG,2).AND.IER1.EQ.0) THEN
+		 CALL SET2(SYSTEM_FLAG,FOLDER1_NUMBER)
+	      END IF
+	   END DO
+	   VERSION(1) = 168
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,2)) THEN
+	   CALL SET2(SYSTEM_FLAG,FOLDER_NUMBER)
+	ELSE
+	   CALL CLR2(SYSTEM_FLAG,FOLDER_NUMBER)
+	END IF
+
+	CALL SYS_BINTIM('-',UP_BTIM)	! Get today's date
+	DIFF = COMPARE_BTIM(SHUTDOWN_BTIM,UP_BTIM)
+	IF (DIFF.GE.0) THEN	! Must have been in a time wrap
+	   SHUTDOWN_BTIM(1) = UP_BTIM(1)
+	   SHUTDOWN_BTIM(2) = UP_BTIM(2)
+	END IF
+
+	CALL GET_UPTIME(UPDATE,UPTIME)
+
+	CALL SYS_BINTIM(UPDATE//' '//UPTIME,UP_BTIM)
+
+	IF (NODE_AREA.EQ.0) THEN
+	   IF (SHUTDOWN_BTIM(1).EQ.0) THEN
+	      DIFF = -1
+	   ELSE
+	      DIFF = COMPARE_BTIM(SHUTDOWN_BTIM,UP_BTIM)
+	   END IF
+	   IF (DIFF.EQ.-1) THEN
+	      CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	      SHUTDOWN_BTIM(1) = UP_BTIM(1)
+	      SHUTDOWN_BTIM(2) = UP_BTIM(2)
+	      DO I=1,FLONG
+		 SHUTDOWN_FLAG(I) = SYSTEM_FLAG(I)
+              END DO
+	   END IF
+	ELSE			! Test to make sure NODE_AREA is zero
+	   SEEN_FLAG = 0		! if all of SHUTDOWN_FLAG is zero
+	   DO I=1,FLONG
+	      IF (SHUTDOWN_FLAG(I).NE.0) SEEN_FLAG = 1
+	   END DO
+	   IF (SEEN_FLAG.EQ.0) NODE_AREA = 0
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (4,IOSTAT=IER)
+     &		'*SYSTEM     ',NODENAME,NODE_NUMBER,NODE_AREA,VERSION,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	ELSE
+	   REWRITE (4,IOSTAT=IER)
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,VERSION,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END IF
+
+	CALL READ_PERM
+
+	IF (.NOT.FILE_OPENED) THEN
+	   CALL CLOSE_BULLUSER
+	   IF (REMOTE_SET) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER1) 14,
+     &				BTEST(FOLDER_FLAG,2),NODENAME
+	      IF (IER1.NE.0) THEN
+	         CALL DISCONNECT_REMOTE
+	         IF (.NOT.FILE_OPENED) CALL CLOSE_BULLUSER
+	         RETURN
+	      END IF
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+	
+	SUBROUTINE GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,SYI$_NODE_AREA,%LOC(NODE_AREA))
+	CALL ADD_2_ITMLST(4,SYI$_NODE_NUMBER,%LOC(NODE_NUMBER))
+	CALL END_ITMLST(GETSYI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETSYIW(,,,%VAL(GETSYI_ITMLST),,,)	! Get Info command.
+C
+C  NODE_AREA is set to 0 after shutdown messages are deleted.
+C  If node is not part of cluster, NODE_AREA will be 0,
+C  so set it to 1 as a dummy value to cause messages to be deleted.
+C
+	IF (NODE_AREA.EQ.0) NODE_AREA = 1
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_NODE(NODE_SET)
+C
+C  SUBROUTINE SET_NODE
+C
+C  FUNCTION: Set or reset remote node specification for selected folder.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER RESPONSE*4,FOLDER_SAVE*44
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (CLI$PRESENT('FOLDER')) THEN
+	   IER = CLI$GET_VALUE('FOLDER',FOLDER1) ! Get folder name
+	   FOLDER_SAVE = FOLDER
+	   CALL OPEN_BULLFOLDER_SHARED		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER1,IER)
+	   IF (IER.EQ.0) THEN
+	      IF (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+		 WRITE (6,'('' ERROR: No privs to modify folder.'')')
+		 IER = 1
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: Specified folder not found.'')')
+	   END IF
+	   IF (IER.NE.0) THEN
+	      CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER)
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   END IF
+	   CALL CLOSE_BULLFOLDER
+	END IF
+
+	IF (FOLDER_NUMBER.EQ.0) THEN
+	   WRITE (6,'('' Cannot set remote node for the default folder.'')')
+	ELSE IF (FOLDER_NUMBER.LT.0.OR.FOLDER_NUMBER.GE.1000) THEN
+	   WRITE (6,'('' Cannot set remote node for this folder.'')')
+	ELSE IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   IF (.NOT.NODE_SET) THEN
+	      IF (INDEX(FOLDER_BBOARD,'*').GT.0) THEN
+		 REMOTE_SET_SAVE = REMOTE_SET
+		 REMOTE_SET = .FALSE.
+	         FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		     FOLDER
+	         CALL OPEN_BULLDIR		! Remove directory file which
+	         CALL CLOSE_BULLDIR_DELETE	! contains remote folder name
+		 REMOTE_SET = REMOTE_SET_SAVE
+	      END IF
+	      FOLDER1_BBOARD = 'NONE'
+	      WRITE (6,'('' Remote node setting has been removed.'')')
+	      IF (.NOT.CLI$PRESENT('FOLDER')) REMOTE_SET = .FALSE.
+	   ELSE
+	      CALL GET_INPUT_PROMPT(RESPONSE,RLEN,
+     &          'Are you sure you want to make folder '//
+     &	        FOLDER(:TRIM(FOLDER))//
+     &		' remote? (Y/N with N as default): ')
+	      IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+	        WRITE (6,'('' Folder was not modified.'')')
+	        RETURN
+	      END IF
+	      IF (.NOT.CLI$GET_VALUE('REMOTENAME',FOLDER1)) THEN
+	         FOLDER1 = FOLDER
+	      END IF
+	      IER = CLI$GET_VALUE('NODENAME',FOLDER1_BBOARD,FLEN)
+	      FOLDER1_BBOARD = '::'//FOLDER1_BBOARD(:FLEN)
+	      CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      IF (IER.NE.0) THEN
+	         WRITE (6,'(
+     &		  '' ERROR: Folder not accessible on remote node.'')')
+	         RETURN
+	      ELSE
+	         WRITE (6,'('' Folder has been converted to remote.'')')
+	      END IF
+	      FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		FOLDER
+	      REMOTE_SET_SAVE = REMOTE_SET
+	      REMOTE_SET = .FALSE.
+	      CALL OPEN_BULLDIR			! Remove directory file
+	      CALL OPEN_BULLFIL			! Remove bulletin file
+	      CALL CLOSE_BULLFIL_DELETE
+	      CALL CLOSE_BULLDIR_DELETE
+	      IF (FOLDER.NE.FOLDER1) THEN	! Different remote folder name?
+	         CALL OPEN_BULLDIR		! If so, put name in header
+		 BULLDIR_HEADER(13:) = FOLDER1	! of directory file.
+		 CALL WRITEDIR_NOCONV(0,IER)
+	         CALL CLOSE_BULLDIR
+	         FOLDER1_BBOARD = FOLDER1_BBOARD(:FLEN+2)//'*'
+	      END IF
+	      REMOTE_SET = REMOTE_SET_SAVE
+	      IF (.NOT.CLI$PRESENT('FOLDER')) REMOTE_SET = .TRUE.
+	   END IF
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   IF (.NOT.NODE_SET.AND.FOLDER_BBOARD(:2).EQ.'::'
+     &			.AND.BTEST(FOLDER_FLAG,2)) THEN
+	      OPEN (UNIT=17,STATUS='UNKNOWN',IOSTAT=IER,
+     &		RECL=256,FILE=FOLDER_BBOARD(3:TRIM(FOLDER_BBOARD))
+     &		//'::"TASK=BULLETIN1"')
+	      IF (IER.EQ.0) THEN	! Disregister remote SYSTEM folder
+		 WRITE(17,'(2A)',IOSTAT=IER) 14,0
+		 CLOSE (UNIT=17)
+	      END IF
+	   END IF
+	   FOLDER_BBOARD = FOLDER1_BBOARD
+	   IF (NODE_SET) THEN
+	      F_NBULL = F1_NBULL
+	      F_NEWEST_BTIM(1) = F1_NEWEST_BTIM(1)
+	      F_NEWEST_BTIM(2) = F1_NEWEST_BTIM(2)
+	      F_NEWEST_NOSYS_BTIM(1) = F1_NEWEST_NOSYS_BTIM(1)
+	      F_NEWEST_NOSYS_BTIM(2) = F1_NEWEST_NOSYS_BTIM(2)
+	      FOLDER_FLAG = 0
+	      F_EXPIRE_LIMIT = F1_EXPIRE_LIMIT
+	   ELSE
+	      F_NBULL = 0
+	   END IF
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLFOLDER
+	ELSE
+	   WRITE (6,'('' You are not authorized to modify NODE.'')')
+	END IF
+
+	IF (CLI$PRESENT('FOLDER')) THEN
+	   CALL OPEN_BULLFOLDER_SHARED		! Open folder file
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER_SAVE,IER)
+	   CALL CLOSE_BULLFOLDER
+	   FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		FOLDER
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE RESPOND
+C
+C  SUBROUTINE RESPOND
+C
+C  FUNCTION: Sends a mail message in reply to a posted message.
+C
+C  NOTE: Modify the last SPAWN statement to specify the command
+C	you use to send mail to sites other than via MAIL.
+C	If you always use a different command, modify both
+C	spawn commands.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	COMMON /INDESCRIP/ INDESCRIP
+	CHARACTER*(INPUT_LENGTH) INDESCRIP
+
+	CHARACTER INFROM*(INPUT_LENGTH)
+
+	EXTERNAL CLI$_NEGATED,CLI$_ABSENT
+
+	MSG_OWN = .FALSE.
+
+	IF (INCMD(:4).EQ.'REPL') THEN
+	   IF (REMOTE_SET.GE.3) THEN
+              BULL_PARAMETER = 'news group.'
+           ELSE
+              BULL_PARAMETER = 'mailing list.'
+           END IF
+	   IF (CLI$PRESENT('ALL')) THEN
+	      IF (REMOTE_SET.GE.3) THEN
+                 BULL_PARAMETER = 'message owner and news group.'
+              ELSE
+                 BULL_PARAMETER = 'message owner and mailing list.'
+              END IF
+	      MSG_OWN = .TRUE.
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'RESP') THEN
+	   MSG_OWN = .TRUE.
+	   BULL_PARAMETER = 'message owner.'
+	   IF (CLI$PRESENT('LIST')) THEN 
+	      IF (REMOTE_SET.GE.3) THEN 
+	   	 BULL_PARAMETER = 'message owner and news group.'
+	      ELSE
+		 BULL_PARAMETER = 'message owner and mailing list.'
+	      END IF
+
+	   END IF
+	ELSE IF (REMOTE_SET.GE.3) THEN 
+	   BULL_PARAMETER = 'news group.'
+	ELSE
+	   BULL_PARAMETER = 'mailing list.'
+	END IF
+
+	LIST = INDEX(BULL_PARAMETER,'mailing list')
+	IF (NEWS_FEED().AND.LIST.GT.0) THEN
+	   BULL_PARAMETER(LIST:) = 'news group'//
+     &				   BULL_PARAMETER(LIST+LEN('mailing list'):)
+	END IF
+
+	IF (MSG_OWN.AND.BTEST(CAPTIVE(-1),1)) THEN
+           WRITE (6,'('' ERROR: MAIL invalid from DISMAIL account.'')')
+           RETURN
+	END IF
+
+	WRITE (6,'('' Sending message to '',A)')
+     &	   BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+
+	IF (INCMD(:4).NE.'POST') THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	      WRITE(6,'('' ERROR: You have not read any message.'')')
+	      RETURN			! And return
+	   END IF
+
+	   CALL OPEN_BULLDIR_SHARED
+
+	   CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin
+
+	   IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
+	      WRITE(6,'('' ERROR: Bulletin was not found.'')')
+	      CALL CLOSE_BULLDIR		! If not, then error out
+	      RETURN
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      INDESCRIP = INPUT(7:)
+	   ELSE
+	      INDESCRIP = DESCRIP
+	   END IF
+
+	   CALL CLOSE_BULLFIL
+
+	   CALL CLOSE_BULLDIR
+
+	   IF (STREQ(INDESCRIP(:3),'RE:')) THEN
+	      INDESCRIP = 'Re:'//INDESCRIP(4:)
+	   ELSE
+	      INDESCRIP = 'Re: '//INDESCRIP
+	   END IF
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN 
+	   IF (CLI$PRESENT('EXPIRATION')) THEN
+	      CALL GET_EXPIRED(INPUT,IER)
+	      IF (.NOT.IER) RETURN
+	      EXDATE = INPUT(:11)
+	      EXTIME = INPUT(13:23)
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SUBJECT')) THEN
+	   IER = CLI$GET_VALUE('SUBJECT',INDESCRIP,LENDES)
+	   IF (LENDES.GT.LEN(INDESCRIP)) THEN
+	      WRITE(6,'('' ERROR: Subject length exceeded.'')')
+	      RETURN
+	   END IF
+	ELSE IF (INCMD(:4).EQ.'POST') THEN
+	   WRITE(6,'('' Enter subject of message:'')')
+	   CALL GET_LINE(INDESCRIP,LENDES)
+	   IF (LENDES.LE.0) THEN
+	      WRITE(6,'('' ERROR: No subject specified.'')')
+	      RETURN
+	   END IF
+	ELSE
+	   WRITE (6,'('' Message will have the subject:'')')
+	   WRITE (6,'(1X,A)') INDESCRIP(:MIN(TRIM(INDESCRIP),PAGE_WIDTH))
+	END IF
+
+	IF ((CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.	! If /EDIT specified
+     &      (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))) THEN
+	   EDIT = .TRUE.
+	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	ELSE
+	   EDIT = .FALSE.
+	END IF
+
+	TEXT = CLI$PRESENT('EXTRACT')
+
+	LIST = CLI$PRESENT('LIST')
+
+	ILEN = 0
+
+	FILESPEC = CLI$GET_VALUE('FILESPEC',INPUT,ILEN)
+	IF (FILESPEC.NE.%LOC(CLI$_ABSENT)) THEN
+	   CALL DISABLE_PRIVS
+	   OPEN (UNIT=4,FILE=INPUT(:ILEN),STATUS='OLD',READONLY,
+     &		 SHARED,IOSTAT=IER,FORM='FORMATTED')
+	   CALL ENABLE_PRIVS
+	   IF (IER.NE.0) THEN
+	      WRITE(6,'('' ERROR: Specified file cannot be opened.'')')
+	      RETURN
+           END IF 
+	END IF
+
+	FOUNDFILE = FILESPEC
+
+	IF (EDIT.AND.(TEXT.OR.FILESPEC)) THEN
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH+2,STATUS='NEW',CARRIAGECONTROL='LIST')
+
+	   IF (IER.NE.0) THEN
+	      CALL ERRSNS(IDUMMY,IER)
+	      CALL SYS_GETMSG(IER)
+	      GO TO 900
+	   END IF
+	ELSE IF (TEXT.AND..NOT.EDIT) THEN
+	   WRITE (6,'('' ERROR: Cannot extract text without /EDIT.'')')
+	   GO TO 900
+	END IF
+
+	LENFRO = 0
+	DO WHILE (CLI$GET_VALUE('CC',INPUT,ILEN)
+     &	    .NE.%LOC(CLI$_ABSENT))		
+	   CALL ADD_PROTOCOL(INPUT,ILEN)
+	   IF (LENFRO.EQ.0) THEN
+	      INFROM = INPUT(:ILEN)//','
+	   ELSE
+	      INFROM = INFROM(:LENFRO)//INPUT(:ILEN)//','
+	   END IF
+	   LENFRO = LENFRO + ILEN + 1
+	END DO
+	IF (LENFRO.GT.0.AND..NOT.MSG_OWN) LENFRO = LENFRO - 1
+
+	IF ((EDIT.AND.TEXT).OR.INCMD(:4).NE.'POST') THEN
+	   CALL OPEN_BULLFIL_SHARED
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (MSG_OWN) THEN
+	         ILEN = TRIM(INPUT) - 6
+	         INFROM = INFROM(:LENFRO)//INPUT(7:)
+		 IF (INDEX(INFROM,' "').GT.INDEX(INFROM,'@')) THEN
+		    I = INDEX(INFROM,' "')
+		    INFROM = INFROM(:I-1)//
+     &			     INFROM(INDEX(INFROM(I+2:),'"')+I+2:)
+		    DO WHILE (INDEX(INFROM,'""').GT.0)
+		       INFROM = INFROM(:INDEX(INFROM,'""'))//
+     &				INFROM(INDEX(INFROM,'""')+2:)
+		    END DO
+	         END IF
+	         CALL ADD_PROTOCOL(INFROM(LENFRO+1:),ILEN)
+	         LENFRO = LENFRO + ILEN
+	      END IF
+	      IF (EDIT.AND.TEXT) THEN
+		 INPUT = INPUT(7:)
+		 IF (INDEX(INPUT,'%"').GT.0) THEN
+		    INPUT = INPUT(INDEX(INPUT,'%"')+2:TRIM(INPUT)-1)
+		 END IF
+	         WRITE (3,'(A)') 'In a previous article, '//
+     &			INPUT(:TRIM(INPUT))//' wrote:'
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE IF (MSG_OWN) THEN
+	      CALL ADD_PROTOCOL(FROM,0)
+	      INFROM = INFROM(:LENFRO)//FROM
+	      LENFRO = TRIM(FROM) + LENFRO
+	   END IF
+
+	   IF (EDIT.AND.TEXT) THEN
+	      IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END IF
+	      LEN_P = 0
+	      IF (CLI$PRESENT('INDENT').NE.%LOC(CLI$_NEGATED)) THEN
+	         CALL CLI$GET_VALUE('INDENT',BULL_PARAMETER,LEN_P)
+	      END IF
+	      DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	         IF (LEN_P.EQ.0) THEN
+	            WRITE (3,'(A)') INPUT(:ILEN)
+	         ELSE
+	            WRITE (3,'(A)') BULL_PARAMETER(:LEN_P)//INPUT(:ILEN)
+	         END IF
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      END DO
+
+	      IF (FILESPEC) THEN
+		 WRITE (3,'(A)') ' '
+		 IER = 0
+		 DO WHILE (IER.EQ.0)
+		    READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		    IF (IER.EQ.0) WRITE (3,'(A)') INPUT(:ILEN)
+		 END DO
+		 CLOSE (UNIT=4)
+	         FILESPEC = .FALSE.
+	      END IF
+
+	      CLOSE (UNIT=3)			! Bulletin copy completed
+	   END IF
+
+	   CALL CLOSE_BULLFIL
+	END IF
+
+	IF (EDIT.AND.FILESPEC.AND..NOT.TEXT) THEN
+	   IER = 0
+	   ICOUNT = 0
+	   DO WHILE (IER.EQ.0)
+	      READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+	      IF (IER.EQ.0) THEN
+		 WRITE (3,'(A)') INPUT(:ILEN)
+		 ICOUNT = ICOUNT + 1
+	      END IF
+	   END DO
+	   CLOSE (UNIT=4)
+	   FILESPEC = .FALSE.
+	   IF (ICOUNT.EQ.0) THEN
+	      CLOSE (UNIT=3,STATUS='DELETE')
+	   ELSE
+	      CLOSE (UNIT=3)
+	   END IF
+	END IF
+
+	IF (LIST.AND.REMOTE_SET.LT.3) THEN
+	   SLIST = INDEX(FOLDER_DESCRIP,'<')
+	   IF (SLIST.GT.0) THEN
+	      IF (.NOT.NEWS_FEED()) THEN
+		 INPUT = FOLDER_DESCRIP(SLIST+1:)
+		 ILEN = INDEX(INPUT,'>') - 1
+		 IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+		 INPUT = INPUT(:ILEN)
+	         CALL ADD_PROTOCOL(INPUT,ILEN)
+	         IF (LENFRO.GT.0.AND.INFROM(LENFRO:LENFRO).NE.',') THEN
+		    INFROM = INFROM(:LENFRO)//','
+		    LENFRO = LENFRO + 1
+		 END IF
+	         INFROM = INFROM(:LENFRO)//INPUT(:ILEN)
+	         LENFRO = LENFRO + ILEN
+	      ELSE
+		 FOLDER1_DESCRIP = 
+     &			FOLDER_DESCRIP(SLIST+1:TRIM(FOLDER_DESCRIP)-1)
+		 IF (FOLDER1_DESCRIP(1:1).EQ.'@') THEN
+		    WRITE(6,'('' ERROR: Multiple newsgroup feed'',
+     &			'' is present.'')')
+		    GO TO 900
+		 END IF
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: No list address'',
+     &			'' found in folder description.'')')
+	      GO TO 900
+	   END IF
+	END IF
+
+	I = 1		! Must change all " to "" in FROM field
+	DO WHILE (I.LE.LENFRO)
+	   IF (INFROM(I:I).EQ.'"') THEN
+	      INFROM = INFROM(:I)//'"'//INFROM(I+1:)
+	      I = I + 1
+	      LENFRO = LENFRO + 1
+	   END IF
+	   I = I + 1
+	END DO
+
+	STATUS = .TRUE.
+
+	IF (EDIT) THEN
+	   CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	   CONTEXT = 0
+	   IER =  LIB$FIND_FILE('SYS$LOGIN:BULL.SCR',INPUT,CONTEXT)
+	   IF (TEXT.OR.FOUNDFILE) THEN
+	      VERSION = INDEX(INPUT,';') + 1
+	      IF (INPUT(VERSION:VERSION).EQ.'1') THEN
+	         CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+	      ELSE
+	         IER = 0
+	      END IF
+	   ELSE IF (IER) THEN
+	      IER = 0
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      CALL ADD_SIGNATURE(0,'SYS$LOGIN:BULL.SCR',FOLDER_NAME)
+	      IF ((NEWS_FEED().OR.REMOTE_SET.GE.3).AND.LIST) THEN
+	         CALL NEWS_POST('SYS$LOGIN:BULL.SCR',.FALSE.,IER,
+     &			INDESCRIP)
+		 STATUS = IER.EQ.0
+	         IF (IER.EQ.0) THEN
+		    WRITE (6,'('' Message successfully posted.'')')
+	         END IF
+	      END IF
+	      IF (IER.EQ.0.AND.LENFRO.GT.0) THEN
+	         CALL RESPOND_MAIL('SYS$LOGIN:BULL.SCR',INFROM,
+     &			   INDESCRIP,STATUS)
+		 INPUT = INDESCRIP
+		 CALL INCLUDE_SUBJECT(0)
+	      END IF
+	   END IF
+	ELSE
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	   IF (.NOT.FILESPEC) THEN
+	      WRITE (6,'('' Enter message: End with ctrl-z,'',
+     &			 '' cancel with ctrl-c'')')
+	      ILEN = LINE_LENGTH + 1		! Length of input line
+	      ICOUNT = 0			! Character count counter
+	      DO WHILE (ILEN.GE.0)		! Input until no more input
+	         CALL GET_LINE(INPUT,ILEN)	! Get input line
+	         IF (ILEN.GT.LINE_LENGTH) THEN	! Input line too long
+		    WRITE(6,'('' ERROR: Input line length > '',I,
+     &			   ''.  Reinput:'')') LINE_LENGTH
+	         ELSE IF (ILEN.GE.0) THEN	! If good input line entered
+		    ICOUNT = ICOUNT + ILEN		! Update counter
+		    WRITE(3,'(A)') INPUT(:ILEN)	! Save line in scratch file
+	         END IF
+	      END DO
+	   ELSE
+	      IER = 0
+	      ICOUNT = 0
+	      DO WHILE (IER.EQ.0)
+		 READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
+		 IF (IER.EQ.0) THEN
+		    ICOUNT = ICOUNT + 1
+		    WRITE (3,'(A)') INPUT(:ILEN)
+		 END IF
+	      END DO
+	      CLOSE (UNIT=4)
+	      FILESPEC = .FALSE.
+	   END IF
+	   IF (ILEN.EQ.-1.OR.ICOUNT.EQ.0) THEN	! CTRL_C or No lines
+	      CLOSE (UNIT=3)
+	      IER = 1
+	   ELSE
+	      CALL ADD_SIGNATURE(3,' ',FOLDER_NAME)
+	      REWIND (UNIT=3)
+	      IF ((NEWS_FEED().OR.REMOTE_SET.GE.3).AND.LIST) THEN
+	         CALL NEWS_POST('SYS$LOGIN:BULL.SCR',.TRUE.,IER,
+     &			   INDESCRIP)
+		 STATUS = IER.EQ.0
+	         IF (IER.EQ.0)  WRITE (6,'('' Message successfully posted.'')')
+	      ELSE
+		 IER = 0
+	      END IF
+	      CLOSE (UNIT=3)
+	      IF (IER.EQ.0.AND.LENFRO.GT.0) THEN
+		 CALL RESPOND_MAIL('SYS$LOGIN:BULL.SCR',INFROM,
+     &			   INDESCRIP,STATUS)
+		 INPUT = INDESCRIP
+		 CALL INCLUDE_SUBJECT(0)
+	      END IF
+	   END IF
+	END IF
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: No message added.'')')
+	   IF (.NOT.STATUS) THEN
+	      CALL GET_INPUT_PROMPT(INPUT,ILEN,'Do you want to'//
+     &		' save message? (Y/N with N as default): ')
+	      IF (STREQ(INPUT(:1),'Y')) THEN
+		 CALL LIB$RENAME_FILE('SYS$LOGIN:BULL.SCR',
+     &				      'SYS$LOGIN:BULL.SAV')
+		 WRITE (6,'(A)') ' Message saved in SYS$LOGIN:BULL.SAV.'
+	      END IF
+	   END IF
+	END IF
+
+900	IF (FILESPEC) CLOSE (UNIT=4)
+	CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_SIGNATURE(FILEUNIT,FILENAME,FOLDER_NAME)
+C
+C  SUBROUTINE ADD_SIGNATURE
+C
+C  FUNCTION: Adds signature to message being mailed/posted.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) FOLDER_NAME
+
+	CHARACTER*128 BULL_SIGNATURE
+	DATA BULL_SIGNATURE /'SYS$LOGIN:BULL_SIGNATURE.TXT'/
+
+	CHARACTER*256 INPUT
+
+	IF (CLI$PRESENT('NOSIGNATURE')) RETURN
+
+	OPEN (UNIT=4,FILE=BULL_SIGNATURE,STATUS='OLD',READONLY,
+     &		 SHARED,IOSTAT=IER,FORM='FORMATTED')
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=4,FILE='BULL_SIGNATURE',STATUS='OLD',READONLY,
+     &		    SHARED,IOSTAT=IER,FORM='FORMATTED')
+	END IF
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=4,FILE='MX_SIGNATURE',STATUS='OLD',READONLY,
+     &		    SHARED,IOSTAT=IER,FORM='FORMATTED')
+	END IF
+
+	IF (IER.NE.0) RETURN
+
+	IF (FILEUNIT.EQ.0) THEN
+	   OPEN (UNIT=3,FILE=FILENAME,STATUS='OLD',ACCESS='APPEND',
+     &		 IOSTAT=IER,FORM='FORMATTED')
+	END IF
+
+	ICOUNT = 0
+	MATCH = .FALSE.
+	DO WHILE (IER.EQ.0)
+	   READ (4,'(A)',IOSTAT=IER) INPUT
+	   ILEN = TRIM(INPUT)
+	   DO WHILE (.NOT.MATCH.AND.STREQ(INPUT(:6),'START ').AND.IER.EQ.0)
+	      MATCH = STREQ(INPUT(7:ILEN),FOLDER_NAME(:TRIM(FOLDER_NAME)))
+	      READ (4,'(A)',IOSTAT=IER) INPUT
+	      ILEN = TRIM(INPUT)
+	      IF (.NOT.MATCH) THEN
+	         DO WHILE (.NOT.STREQ(INPUT(:ILEN),'END').AND.IER.EQ.0)
+		    READ (4,'(A)',IOSTAT=IER) INPUT
+	            ILEN = TRIM(INPUT)
+		 END DO
+		 READ (4,'(A)',IOSTAT=IER) INPUT
+	         ILEN = TRIM(INPUT)
+	      END IF
+	   END DO
+	   IF (IER.EQ.0) THEN
+	      IF (MATCH.AND.STREQ(INPUT(:ILEN),'END')) THEN
+	         MATCH = .FALSE.
+	      ELSE
+	         ICOUNT = ICOUNT + 1
+	         IF (ICOUNT.EQ.1) WRITE (3,'(A)',IOSTAT=IER) ' '
+	         WRITE (3,'(A)',IOSTAT=IER) INPUT(:ILEN)
+	      END IF
+	   END IF
+	END DO
+
+	CLOSE (UNIT=4)
+	IF (FILEUNIT.EQ.0) CLOSE (UNIT=3)
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION STREQ(INPUT,INPUT1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,INPUT1
+
+	STREQ = .FALSE.
+
+	IF (LEN(INPUT).NE.LEN(INPUT1)) RETURN
+
+	DO I=1,LEN(INPUT)
+	   DIFF = ABS(ICHAR(INPUT(I:I))-ICHAR(INPUT1(I:I)))
+	   IF (DIFF.NE.0.AND.(DIFF.NE.32.OR..NOT.ALPHA(INPUT(I:I))
+     &		  .OR..NOT.ALPHA(INPUT1(I:I)))) RETURN
+	END DO
+
+	STREQ = .TRUE.
+
+	RETURN
+	END
+
+
+
+
+
+
+	SUBROUTINE RESPOND_MAIL(FILE,SENDTO,SUBJECT,STATUS)
+C
+C  SUBROUTINE RESPOND_MAIL
+C
+C  FUNCTION: Sends mail to address.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /MAIL_INFO/ USE_INFROM
+	DATA USE_INFROM /.FALSE./
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /PATH/ PATHNAME,LPATH
+	CHARACTER*132 PATHNAME
+
+	CHARACTER*(*) FILE,SENDTO,SUBJECT
+
+	CHARACTER MAILER*128,MLDESCRIP*(LINE_LENGTH)
+
+	PRIVS = FILE.NE.'SYS$LOGIN:BULL.SCR'
+
+	MLDESCRIP = SUBJECT
+	LENDES = TRIM(MLDESCRIP)
+	I = 1		! Must change all " to "" in SUBJECT field
+	DO WHILE (I.LE.LENDES)
+	   IF (MLDESCRIP(I:I).EQ.'"') THEN
+	      IF (LENDES.EQ.LINE_LENGTH) THEN
+		 MLDESCRIP(I:I) = '`'
+	      ELSE
+		 MLDESCRIP = MLDESCRIP(:I)//'"'
+     &				//MLDESCRIP(I+1:)
+		 I = I + 1
+		 LENDES = LENDES + 1
+	      END IF
+	   END IF
+	   I = I + 1
+	END DO
+
+	LISTSERV = INDEX(FOLDER_DESCRIP,'LISTSERV').GT.0
+	VMSSERV = INDEX(FOLDER_DESCRIP,'VMSSERV').GT.0
+
+	IF (LISTSERV.OR.VMSSERV) CALL SETUSER(FOLDER_BBOARD)
+	IF (PRIVS) CALL DISABLE_PRIVS
+
+	IF (LISTSERV) THEN
+	   IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED')) THEN
+	      IF (.NOT.SYS_TRNLNM('MX_REPLY_TO','DEFINED'))
+     &	         CALL CRELNM('MX_REPLY_TO',USERNAME(:TRIM(USERNAME)))
+	   ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED')) THEN
+	      IF (.NOT.SYS_TRNLNM('PMDF_REPLY_TO','DEFINED'))
+     &	         CALL CRELNM('PMDF_REPLY_TO',USERNAME(:TRIM(USERNAME)))
+	   ELSE
+	      IF (.NOT.SYS_TRNLNM('MULTINET_SMTP_REPLY_TO','DEFINED'))
+     &	         CALL CRELNM('MULTINET_SMTP_REPLY_TO',
+     &		          USERNAME(:TRIM(USERNAME)))
+	   END IF
+	END IF
+
+	IF (USE_INFROM) THEN
+	   IF (INDEX(INFROM,'::').GT.0) THEN
+              IF (LPATH.EQ.0) CALL GET_PATHNAME
+	      IF (LPATH.GT.0) THEN
+		 INFROM = INFROM(INDEX(INFROM,'::')+2:TRIM(INFROM))//
+     &		   	  PATHNAME(:LPATH)
+	      END IF
+	   END IF
+	   IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED')) THEN
+      	      CALL CRELNM('MX_REPLY_TO',INFROM(:TRIM(INFROM)))
+	   ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED')) THEN
+      	      CALL CRELNM('PMDF_REPLY_TO',INFROM(:TRIM(INFROM)))
+	   ELSE
+      	      CALL CRELNM('MULTINET_SMTP_REPLY_TO',INFROM(:TRIM(INFROM)))
+	   END IF
+	END IF
+
+	LEN_SENDTO = TRIM(SENDTO)
+	IF (SYS_TRNLNM('BULL_MAILER',MAILER)) THEN
+	   IF (LISTSERV) THEN
+	      IF (SYS_TRNLNM_SYSTEM('BULL_MAILER',MAILER)) THEN
+	         CALL LIB$SPAWN('@'//MAILER(:TRIM(MAILER))//
+     &		    ' '//FILE(:TRIM(FILE))//' """'//SENDTO(:LEN_SENDTO)
+     &		    //'""" """'//MLDESCRIP(:LENDES)//'""" '
+     &		    //USERNAME(:TRIM(USERNAME)),,,,,,STATUS)
+	      END IF
+	   ELSE
+	      CALL LIB$SPAWN('@'//MAILER(:TRIM(MAILER))//
+     &		 ' '//FILE(:TRIM(FILE))//' """'//SENDTO(:LEN_SENDTO)//
+     &		 '""" """'//MLDESCRIP(:LENDES)//'"""',,,,,,STATUS)
+	   END IF
+	ELSE
+	   I = INDEX(SENDTO,'%""') + 3
+	   DO WHILE (I.LT.LEN_SENDTO-2)
+	      IF (SENDTO(I:I+2).EQ.'"",'.OR.SENDTO(I:I+2).EQ.'%""') THEN
+		 I = I + 3
+	      ELSE IF (SENDTO(I:I+1).EQ.'""') THEN
+		 SENDTO(I:) = ''''//SENDTO(I+2:)
+                 LEN_SENDTO = LEN_SENDTO - 1
+              ELSE IF (SENDTO(I:I).EQ.'\'.AND.
+     &                 SENDTO(I+1:I+1).NE.'\') THEN
+		 SENDTO(I+1:) = '\'//SENDTO(I+1:)
+		 LEN_SENDTO = LEN_SENDTO + 1
+		 I = I + 1
+	      ELSE IF (SENDTO(I:I).EQ.''''.AND.
+     &		       INDEX(SENDTO,'@').GT.I) THEN
+		 SENDTO(I:) = '\s'//SENDTO(I+1:)
+		 LEN_SENDTO = LEN_SENDTO + 1
+		 I = I + 2
+	      END IF
+	      I = I + 1
+	   END DO
+
+           CALL SENDMAIL(FILE(:TRIM(FILE)),SENDTO,
+     &                MLDESCRIP(:LENDES),STATUS)
+           IF (.NOT.STATUS) CALL SYS_GETMSG(STATUS)
+C
+C Use the following if you do not have VMS V5.3 or greater.
+C
+C           CALL LIB$SPAWN('$MAIL SYS$LOGIN:BULL.SCR "'//
+C     &                SENDTO(:LEN_SENDTO)//
+C     &       '" /SUBJECT="'//MLDESCRIP(:LENDES)//'"',,,,,,STATUS)
+	END IF
+
+	IF (PRIVS) CALL ENABLE_PRIVS
+	IF (LISTSERV.OR.VMSSERV) CALL SETUSER(USERNAME)
+	IF (LISTSERV.OR.USE_INFROM) THEN
+	   USE_INFROM = .FALSE.
+	   CALL DELLNM_USER('MULTINET_SMTP_REPLY_TO')
+	   CALL DELLNM_USER('PMDF_REPLY_TO')
+	   CALL DELLNM_USER('MX_REPLY_TO')
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION CONFIRM_USER(USERNAME)
+C
+C  FUNCTION CONFIRM_USER
+C
+C  FUNCTION: Confirms that username is valid user.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) USERNAME
+
+	CALL OPEN_SYSUAF_SHARED
+
+	READ (8,KEY=USERNAME,IOSTAT=CONFIRM_USER)
+
+	CALL CLOSE_SYSUAF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE REPLACE
+C
+C  SUBROUTINE REPLACE
+C
+C  FUNCTION: CHANGE command subroutine.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EDIT/ EDIT_DEFAULT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	CHARACTER INEXDATE*12,INEXTIME*12
+	CHARACTER INDESCRIP*(INPUT_LENGTH),INFROM*(INPUT_LENGTH)
+	CHARACTER*4 ANSWER
+
+	CHARACTER DATE_SAVE*12,TIME_SAVE*12
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	LOGICAL DOALL
+
+	IF (REMOTE_SET.GE.3) THEN
+	   WRITE (6,'('' Cannot CHANGE messages in this folder.'')')
+	   RETURN
+	END IF
+
+C
+C  Get the bulletin number to be replaced.
+C
+
+	ALL = CLI$PRESENT('ALL')
+
+	IER1 = CLI$GET_VALUE('NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER1.EQ.%LOC(CLI$_ABSENT).AND..NOT.ALL) THEN
+	   IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
+	      WRITE (6,1005)		! Tell user of the error
+	      RETURN			! and return
+	   END IF
+	   SBULL = BULL_POINT		! Replace the bulletin we are reading
+	   EBULL = SBULL
+
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(BULL_POINT,IER)		! Get message directory entry
+	   CALL CLOSE_BULLDIR
+	   IF (IER.NE.BULL_POINT+1) THEN	! Was message found?
+	      WRITE(6,'('' ERROR: Specified message was not found.'')')
+	      RETURN
+	   END IF
+	ELSE
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(0,IER)		! Get message directory entry
+	   CALL CLOSE_BULLDIR
+	   IF (NBULL.EQ.0) THEN		! Were messages found?
+	      WRITE(6,'('' ERROR: No messages were found.'')')
+	      RETURN
+	   END IF
+
+	   IF (IER1.NE.%LOC(CLI$_ABSENT)) THEN
+	      CALL GET_2_VALS(BULL_PARAMETER,LEN_P,SBULL,EBULL,IER1)
+	      IF (SBULL.LE.0.OR.IER1.NE.0) THEN
+	         WRITE (6,'(A)') 
+     &		  ' ERROR: Specified message number has incorrect format.'
+	         RETURN
+	      END IF
+	      ALL = .TRUE.
+	   ELSE IF (CLI$PRESENT('ALL')) THEN
+	      SBULL = 1
+	      EBULL = NBULL
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SYSTEM')) THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	    WRITE (6,'(
+     &	     '' ERROR: Not enough privileges to change to system.'')')
+	    RETURN
+	   ELSE IF (.NOT.BTEST(FOLDER_FLAG,2).AND.FOLDER_NUMBER.NE.0) THEN
+	    WRITE (6,'(
+     &       '' ERROR: /SYSTEM cannot be set with selected folder.'')')
+	    RETURN
+	   END IF
+	END IF
+
+	LENFROM = 0
+	IF (CLI$PRESENT('OWNER')) THEN
+	   IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.	! Privileges or
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN				! folder owner?
+	      WRITE(6,1090)		! If not, then error out.
+	      RETURN
+	   ELSE
+	      IER = CLI$GET_VALUE('OWNER',INFROM,LENFROM)
+	      INFROM = 'From: '//INFROM
+	      LENFROM = LENFROM + 6
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('SHUTDOWN')) THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	    WRITE (6,'(
+     &	     '' ERROR: Not enough privileges to change to shutdown.'')')
+	    RETURN
+	   ELSE IF (.NOT.BTEST(FOLDER_FLAG,2).AND.FOLDER_NUMBER.NE.0) THEN
+	    WRITE (6,'(
+     &      '' ERROR: /SHUTDOWN cannot be set with selected folder.'')')
+	    RETURN
+	   ELSE IF (CLI$GET_VALUE('SHUTDOWN',BULL_PARAMETER).NE.
+     &		    %LOC(CLI$_ABSENT).AND.REMOTE_SET) THEN
+	    WRITE (6,'('' ERROR: Shutdown node name not'',
+     &			    '' permitted for remote folder.'')')
+	    RETURN
+	   END IF
+	END IF
+
+	IF (CLI$PRESENT('PERMANENT').AND.
+     &		F_EXPIRE_LIMIT.GT.0.AND..NOT. ! Expiration limit present
+     &		FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   WRITE (6,'(
+     &	    '' ERROR: Not enough privileges to change to permanent.'')')
+	   RETURN
+	END IF
+C
+C  Check to see if specified bulletin is present, and if the user
+C  is permitted to replace the bulletin.
+C
+
+	CALL OPEN_BULLDIR_SHARED
+
+	SAME_OWNER = .TRUE.
+	DO I=SBULL,EBULL
+	   CALL READDIR(I,IER)	! Get info for specified messages
+	   IF (USERNAME.NE.FROM) SAME_OWNER = .FALSE. 
+	END DO
+	CALL READDIR(SBULL,IER)
+
+	CALL CLOSE_BULLDIR
+
+	IF (.NOT.SAME_OWNER) THEN	! If doesn't match owner of bulletin,
+	   IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.	! Privileges or
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN				! folder owner?
+	      WRITE(6,1090)		! If not, then error out.
+	      RETURN
+	   ELSE
+	      WRITE (6,1100)		! Make sure user wants to delete it
+	      READ (5,'(A)',IOSTAT=IER) ANSWER	! Get his answer
+	      CALL STR$UPCASE(ANSWER,ANSWER)	! Convert input to uppercase
+	      IF (ANSWER(:1).NE.'Y') RETURN	! If not Yes, then exit
+	   END IF
+	END IF
+
+C
+C  If no switches were given, replace the full bulletin
+C
+
+	DOALL = .FALSE.
+
+	IF ((.NOT.CLI$PRESENT('EXPIRATION')).AND.
+     &	   (.NOT.CLI$PRESENT('GENERAL')).AND.
+     &	   (.NOT.CLI$PRESENT('SYSTEM')).AND.
+     &	   (.NOT.CLI$PRESENT('HEADER')).AND.
+     &	   (.NOT.CLI$PRESENT('SUBJECT')).AND.
+     &	   (.NOT.CLI$PRESENT('TEXT')).AND.
+     &	   (.NOT.CLI$PRESENT('OWNER')).AND.
+     &	   (.NOT.CLI$PRESENT('SHUTDOWN')).AND.
+     &	   (.NOT.CLI$PRESENT('PERMANENT'))) THEN
+	   DOALL = .TRUE.
+	END IF
+
+	TEXT = CLI$PRESENT('TEXT').OR.CLI$PRESENT('EDIT')
+
+	IF (SBULL.NE.EBULL.AND.(DOALL.OR.TEXT)) THEN
+	   WRITE (6,'('' ERROR: Cannot change text when replacing'',
+     &		      '' more than one messsage.'')')
+	   RETURN
+	END IF
+
+	CALL DISABLE_CTRL			! Disable CTRL-Y & -C
+
+	PERMANENT = .FALSE.
+	IF (CLI$PRESENT('EXPIRATION').OR.DOALL) THEN
+	   SYSTEM = 0
+	   CALL GET_EXPIRED(INPUT,IER)
+	   PERMANENT = BTEST(SYSTEM,1)
+	   IF (.NOT.IER) GO TO 910
+	   INEXDATE = INPUT(:11)
+	   INEXTIME = INPUT(13:23)
+	END IF
+
+8	LENDES = 0
+	IF (CLI$PRESENT('HEADER').OR.DOALL) THEN
+	   WRITE(6,1050)			! Request header for bulletin
+	   READ(5,'(Q,A)',END=910,ERR=910) LENDES,INDESCRIP
+	   IF (LENDES.EQ.0) GO TO 910		! If no header, don't add bull
+	ELSE IF (CLI$PRESENT('SUBJECT')) THEN
+	   IER = CLI$GET_VALUE('SUBJECT',INDESCRIP,LENDES)
+	END IF
+
+	IF (LENDES.GT.0) THEN
+	   INDESCRIP = 'Subj: '//INDESCRIP
+	   LENDES = MIN(LENDES+6,LEN(INDESCRIP))
+	END IF
+ 
+	IF (SBULL.NE.EBULL) CALL OPEN_BULLDIR
+
+	DO NUMBER=SBULL,EBULL
+	 NUMBER_PARAM = NUMBER
+	 IF (SBULL.NE.EBULL) THEN
+	   CALL READDIR(NUMBER_PARAM,IER)
+	   IF (IER.NE.NUMBER_PARAM+1) THEN	! Couldn't find message
+	      CALL CLOSE_BULLDIR
+	      WRITE(6,'('' ERROR: Message '',I6,'' cannot be found.'')')
+     &			NUMBER_PARAM
+	      WRITE(6,'('' All messages up to that message were modified.'')')
+	      RETURN
+	   END IF
+	 END IF
+
+	 REC1 = 0
+
+	 IF (LENDES.GT.0.OR.TEXT.OR.DOALL.OR.LENFROM.GT.0) THEN
+	   OPEN(UNIT=3,FILE='SYS$LOGIN:BULL.SCR',IOSTAT=IER,
+     &	     RECL=LINE_LENGTH,STATUS='SCRATCH',CARRIAGECONTROL='LIST')
+
+	   IF (IER.NE.0) THEN
+	      CALL ERRSNS(IDUMMY,IER)
+	      CALL SYS_GETMSG(IER)
+	      GO TO 910
+	   END IF
+
+	   CALL OPEN_BULLFIL_SHARED
+
+	   REC1 = 1
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      IF (LENFROM.EQ.0) THEN
+	         INFROM = INPUT(:ILEN)
+	         LENFROM = ILEN
+ 	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      IF (LENDES.EQ.0.AND..NOT.DOALL) THEN
+		 INDESCRIP = INPUT(:ILEN)
+		 LENDES = ILEN
+	      END IF
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)		! Copy bulletin into file
+	      WRITE (3,'(A)') INPUT(:ILEN)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   END DO
+
+	   CALL CLOSE_BULLFIL
+
+	   IF (TEXT.OR.DOALL) CLOSE(UNIT=3)
+	 END IF
+
+	 IF (TEXT.OR.DOALL) THEN
+C
+C  If file specified in REPLACE command, read file to obtain bulletin.
+C  Else, read the bulletin from the terminal.
+C
+	
+	  ICOUNT = 0				! Line count for bulletin
+	  LAST_NOBLANK = 0			! Last line with data
+	  REC1 = 1
+
+	  IER = CLI$GET_VALUE('FILESPEC',BULL_PARAMETER,LEN_P)
+	  IF (IER.NE.%LOC(CLI$_ABSENT).OR.	! If file param in ADD command
+     &	    ((CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.	! or /EDIT specified
+     &       (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED)))) THEN
+
+	   IF ((CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND. ! If /EDIT specified
+     &       (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))) THEN
+	      IF (LEN_P.EQ.0) THEN		! If no file param specified
+		 IF (.NOT.CLI$PRESENT('NEW')) THEN
+	            OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='NEW',
+     &		       RECL=LINE_LENGTH,
+     &		       ERR=920,FORM='FORMATTED',CARRIAGECONTROL='LIST')
+	            CALL OPEN_BULLFIL_SHARED	! Prepare to copy message
+		    ILEN = LINE_LENGTH + 1
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END IF
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END IF
+		    DO WHILE (ILEN.GT.0)	! Copy message into file
+		       WRITE (3,'(A)') INPUT(:ILEN)
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END DO
+		    CALL CLOSE_BULLFIL
+	            CLOSE (UNIT=3)		! Bulletin copy completed
+		 END IF
+		 CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	      ELSE 
+	         CALL DISABLE_PRIVS
+		 CALL MAILEDIT(BULL_PARAMETER(:LEN_P),'SYS$LOGIN:BULL.SCR')
+	      END IF
+	      IER = LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;-1')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 DISPOSE='DELETE',ERR=920,FORM='FORMATTED')
+	   ELSE IF (LEN_P.GT.0) THEN
+	      CALL DISABLE_PRIVS
+	      OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED') ! Try opening the file
+	   END IF
+
+	   CALL ENABLE_PRIVS			! Reset SYSPRV privileges
+
+	   DO WHILE(1)				! Read until end of file to
+	      READ (3,'(Q,A)',END=10) ILEN,INPUT	! get record count
+	      IF (ILEN.GT.LINE_LENGTH) GO TO 950
+	      CALL STR$TRIM(INPUT,INPUT,ILEN)
+	      IF (ILEN.GT.0) THEN		! If good input line entered
+		 ICOUNT = ICOUNT + ILEN + 1	! Increment record count
+		 LAST_NOBLANK = ICOUNT
+	      ELSE IF (ILEN.EQ.0) THEN
+		 IF (ICOUNT.GT.0) THEN
+		    ICOUNT = ICOUNT + 2		! COPY_BULL writes a line with
+		 ELSE				! 1 space for a blank line.
+		    REC1 = REC1 + 1
+		 END IF
+	      END IF
+	   END DO
+	  ELSE					! If no input file
+	   OPEN (UNIT=3,STATUS='NEW',FILE='SYS$LOGIN:BULL.SCR',ERR=920,
+     &		 DISPOSE='DELETE',FORM='FORMATTED',RECL=LINE_LENGTH,
+     &		 CARRIAGECONTROL='LIST')	! Scratch file to save bulletin
+	   WRITE (6,1000)		! Request bulletin input from terminal
+	   ILEN = LINE_LENGTH			! Length of input line
+	   DO WHILE (ILEN.GE.0)			! Input until no more input
+	      CALL GET_LINE(INPUT,ILEN)		! Get input line
+	      IF (ILEN.GT.LINE_LENGTH) THEN	! Line too long.
+		 WRITE(6,'('' ERROR: Input line length > '',I,
+     &			''. Reinput::'')') LINE_LENGTH
+	      ELSE IF (ILEN.GT.0) THEN		! If good input line entered
+		 ICOUNT = ICOUNT + 1 + ILEN	! Increment character count
+		 WRITE(3,'(A)') INPUT(:ILEN)	! Save line in scratch file
+		 LAST_NOBLANK = ICOUNT
+	      ELSE IF (ILEN.EQ.0.AND.ICOUNT.GT.0) THEN
+		 WRITE(3,'(A)') INPUT(:ILEN)	! Save line in scratch file
+		 ICOUNT = ICOUNT + 2		! COPY_BULL writes a line with
+	      END IF				! 1 space for a blank line.
+	   END DO
+	   IF (ILEN.EQ.-1) GO TO 910		! CTRL_C entered, error out
+10	   ICOUNT = LAST_NOBLANK
+	   IF (ICOUNT.EQ.0) GO TO 910		! No lines entered, error out
+	  ENDIF
+
+	 END IF
+
+C
+C  Add bulletin to bulletin file and directory entry for to directory file.
+C
+
+	 DATE_SAVE = DATE
+	 TIME_SAVE = TIME
+	 INPUT = DESCRIP
+
+	 IF (SBULL.EQ.EBULL) THEN
+	  CALL OPEN_BULLDIR			! Prepare to add dir entry
+	  CALL READDIR(NUMBER_PARAM,IER)	! Get info for message
+
+	  IF (IER.NE.NUMBER_PARAM+1.OR.DATE.NE.DATE_SAVE.OR.
+     &	     TIME.NE.TIME_SAVE.OR.INPUT.NE.DESCRIP) THEN
+				! If message disappeared, try to find it.
+	   IF (IER.NE.NUMBER_PARAM+1) DATE = ' '
+	   NUMBER_PARAM = 0
+	   IER = 1
+	   DO WHILE (IER.EQ.NUMBER_PARAM+1.AND.
+     &	    (DATE.NE.DATE_SAVE.OR.TIME.NE.TIME_SAVE.OR.DESCRIP.NE.INPUT))
+	      NUMBER_PARAM = NUMBER_PARAM + 1
+	      CALL READDIR(NUMBER_PARAM,IER)
+	   END DO
+
+	   IF (IER.NE.NUMBER_PARAM+1) THEN	! Couldn't find message
+	      CALL CLOSE_BULLDIR
+	      CLOSE (UNIT=3,STATUS='SAVE')
+	      WRITE(6,'('' ERROR: Message has been deleted'',
+     &			'' by another user.'')')
+	      IF (DOALL.OR.TEXT) THEN
+		 WRITE (6,'('' New text has been saved in'',
+     &				'' SYS$LOGIN:BULL.SCR.'')')
+	      END IF
+	      GO TO 100
+	   END IF
+	  END IF
+	 END IF
+
+	 CALL READDIR(0,IER)			! Get directory header
+
+	 IF (REC1.GT.0) THEN			! If text has been replaced
+
+	   CALL OPEN_BULLFIL			! Prepare to add bulletin
+
+	   BLOCK = NBLOCK + 1
+	   BLOCK_SAVE = BLOCK
+	   NEMPTY = NEMPTY + LENGTH
+
+	   OBLOCK = BLOCK
+	   IF (LENFROM.GT.0) THEN
+	      CALL STORE_BULL(LENFROM,INFROM(:LENFROM),OBLOCK)
+	   END IF
+	   IF (LENDES.GT.0) THEN
+	      CALL STORE_BULL(LENDES,INDESCRIP(:LENDES),OBLOCK)
+	   END IF
+	   REWIND (UNIT=3)
+	   CALL COPY_BULL(3,REC1,OBLOCK,IER)	! Add the new bulletin
+	   IF (IER.NE.0) THEN		! Error in creating bulletin
+	      WRITE (6,'(A)') ' ERROR: Unable to replace message.'
+	      CALL CLOSE_BULLFIL
+	      CALL CLOSE_BULLDIR
+	      CLOSE (UNIT=3)
+	      GO TO 100
+	   END IF
+
+	   LENGTH_SAVE = OCOUNT - BLOCK + 1
+	   NBLOCK = NBLOCK + LENGTH_SAVE
+
+	   IF (.NOT.REMOTE_SET) CALL WRITEDIR(0,IER)
+
+	   CALL CLOSE_BULLFIL
+
+	   IF (.NOT.REMOTE_SET) THEN
+	    CALL READDIR(NUMBER_PARAM,IER)	! Get directory entry
+	    LENGTH = LENGTH_SAVE		! Update size
+	    BLOCK = BLOCK_SAVE
+	    CALL WRITEDIR(NUMBER_PARAM,IER)	! Write new directory entry
+	   END IF
+	 ELSE
+	   CALL READDIR(NUMBER_PARAM,IER)
+	 END IF
+
+	 IF (.NOT.REMOTE_SET) THEN
+
+	   IF (LENDES.GT.0.OR.DOALL) THEN
+	      DESCRIP=INDESCRIP(7:62)		! Update description header
+	   END IF
+	   CALL UPDATE_DIR_HEADER((CLI$PRESENT('EXPIRATION').OR.DOALL).AND.
+     &		.NOT.PERMANENT,CLI$PRESENT('PERMANENT').OR.PERMANENT,
+     &		CLI$PRESENT('SHUTDOWN'),INEXDATE,INEXTIME)
+	   IF (CLI$PRESENT('SYSTEM')) THEN
+	      SYSTEM = IBSET(SYSTEM,0)
+	   ELSE IF (CLI$PRESENT('GENERAL')) THEN
+	      SYSTEM = IBCLR(SYSTEM,0)
+	   END IF
+	   IF (CLI$PRESENT('OWNER')) THEN
+	      CALL GET_FROM(FROM,INFROM(7:),LENFROM-6)
+	      CALL STR$UPCASE(FROM,FROM)
+	   END IF
+	   CALL WRITEDIR(NUMBER_PARAM,IER)
+	 ELSE
+	   MSGTYPE = 0
+	   IF (CLI$PRESENT('SYSTEM').OR.
+     &		(BTEST(SYSTEM,0).AND..NOT.CLI$PRESENT('GENERAL'))) THEN
+	      MSGTYPE = IBSET(MSGTYPE,0)
+	   END IF
+	   IF (CLI$PRESENT('PERMANENT').OR.PERMANENT) THEN
+	      MSGTYPE = IBSET(MSGTYPE,1)
+	   ELSE IF (CLI$PRESENT('SHUTDOWN')) THEN
+	      MSGTYPE = IBSET(MSGTYPE,2)
+	   ELSE IF ((CLI$PRESENT('EXPIRATION').OR.DOALL)
+     &		    .AND..NOT.PERMANENT) THEN
+	      MSGTYPE = IBSET(MSGTYPE,3)
+	   END IF
+	   IF (LENDES.EQ.0.AND..NOT.DOALL) INDESCRIP(7:) = DESCRIP
+	   IF (CLI$PRESENT('EXPIRATION').OR.DOALL) THEN
+	      EXDATE = INEXDATE
+	      EXTIME = INEXTIME
+	   END IF
+	   WRITE (REMOTE_UNIT,'(7A)',IOSTAT=IER)
+     &      10,DESCRIP,NUMBER_PARAM,INDESCRIP(7:62),MSGTYPE,
+     &	    EXDATE,EXTIME
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (I.NE.LEN(FOLDER1_COM)) THEN
+		 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      END IF
+	   ELSE
+	      CALL DISCONNECT_REMOTE
+	   END IF
+	 END IF
+	END DO
+
+	CALL CLOSE_BULLDIR		! Totally finished with replace
+
+	CLOSE (UNIT=3)
+
+100	CALL ENABLE_CTRL		! Enable CTRL-Y & -C
+	RETURN
+
+910	WRITE(6,1010)
+	CLOSE (UNIT=3,ERR=100)
+	GOTO 100
+
+920	WRITE(6,1020)
+	CALL ENABLE_PRIVS	! Reset SYSPRV privileges
+	GOTO 100
+
+950	WRITE (6,1030) LINE_LENGTH
+	CLOSE (UNIT=3)
+	GO TO 100
+
+1000	FORMAT (' Enter message: End with ctrl-z, cancel with ctrl-c')
+1005	FORMAT (' ERROR: You are not reading any message.')
+1010	FORMAT (' No message was replaced.')
+1015	FORMAT (' ERROR: Specified message was not found.')
+1020	FORMAT (' ERROR: Unable to open specified file.')
+1030	FORMAT (' ERROR: Line length in file exceeds '',I,'' characters.')
+1050	FORMAT (' Enter description header.')
+1090	FORMAT(' ERROR: Specified message is not owned by you.')
+1100	FORMAT(' Message(s) is not owned by you.',
+     &	       ' Are you sure you want to replace it? ',$)
+2020	FORMAT(1X,A)
+
+	END
+
+
+
+	SUBROUTINE UPDATE_DIR_HEADER(EXPIRE,PERM,SHUT,INEXDATE,INEXTIME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	CHARACTER TODAY*24,INEXDATE*12,INEXTIME*12
+
+	IF (EXPIRE) THEN
+	   SYSTEM = IBCLR(SYSTEM,1)
+	   SYSTEM = IBCLR(SYSTEM,2)
+	   EXDATE=INEXDATE			! Update expiration date
+	   EXTIME=INEXTIME
+	   DIFF = COMPARE_DATE(EXDATE,NEWEST_EXDATE)	! Compare expiration
+	   IF (DIFF.EQ.0) DIFF = COMPARE_TIME(EXTIME,NEWEST_EXTIME)
+	   IF (DIFF.LT.0) THEN			! If it's oldest expiration bull
+	      NEWEST_EXDATE = EXDATE		! Update the header in
+	      NEWEST_EXTIME = EXTIME		! the directory file
+	      CALL WRITEDIR(0,IER)
+	   END IF
+	ELSE IF (PERM.AND.(.NOT.BTEST(SYSTEM,1))) THEN
+	   IF (BTEST(SYSTEM,2)) THEN
+	      SYSTEM = IBCLR(SYSTEM,2)
+	      SHUTDOWN = SHUTDOWN - 1
+	      CALL WRITEDIR(0,IER)
+	   END IF
+	   SYSTEM = IBSET(SYSTEM,1)
+	   EXDATE = '5-NOV-2100'
+	   EXTIME = '00:00:00.00'
+	ELSE IF (SHUT.AND.(.NOT.BTEST(SYSTEM,2))) THEN
+	   SYSTEM = IBSET(SYSTEM,2)
+	   SYSTEM = IBCLR(SYSTEM,1)
+	   EXDATE = '5-NOV-2100'
+	   NODE_AREA = 0
+	   IF (INCMD(:4).EQ.'REPL') THEN
+	      IF (CLI$GET_VALUE('SHUTDOWN',NODE_NAME)
+     &		    .NE.%LOC(CLI$_ABSENT)) THEN
+		 CALL GET_NODE_NUMBER_OTHER(NODE_NUMBER,NODE_AREA,NODE_NAME)
+	         IF (NODE_AREA.EQ.0) THEN
+		    WRITE (6,'('' ERROR: Shutdown node name ignored.'',
+     &		               '' Invalid node name specified.'')')
+		 END IF
+	      END IF
+	   END IF
+	   IF (NODE_AREA.EQ.0) CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	   WRITE (EXTIME,'(I4)') NODE_NUMBER
+	   WRITE (EXTIME(7:),'(I4)') NODE_AREA
+	   DO I=1,11
+	      IF (EXTIME(I:I).EQ.' ') EXTIME(I:I) = '0'
+	   END DO
+	   EXTIME = EXTIME(1:2)//':'//EXTIME(3:4)//':'//
+     &		    EXTIME(7:8)//'.'//EXTIME(9:10)
+	   SHUTDOWN = SHUTDOWN + 1
+	   CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	   SHUTDOWN_DATE = TODAY(:11)
+	   SHUTDOWN_TIME = TODAY(13:)
+	   CALL WRITEDIR(0,IER)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SEARCH(READ_COUNT)
+C
+C  SUBROUTINE SEARCH
+C
+C  FUNCTION: Search for bulletin with specified string
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	CHARACTER*132 SEARCH_STRING
+	DIMENSION SEARCH_LEN(10)
+
+        CHARACTER GROUP*80,STAT*4
+
+	EXTERNAL CLI$_ABSENT
+
+	IF (CLI$PRESENT('NOREPLIES')) THEN
+	   SEARCH_STRING = 'RE:'
+	   SEARCH_LEN(1) = 3
+	   SEARCH_NUM = 1
+	   NFOLDER = 1
+	ELSE IF (CLI$PRESENT('REPLY')) THEN
+	   SEARCH_STRING = ' '
+	   SEARCH_NUM = 1
+	   NFOLDER = 1
+	   INPUT = DESCRIP
+	   CALL INCLUDE_SUBJECT(0)
+	ELSE IF (CLI$PRESENT('SEARCH_STRING')) THEN
+	   SEARCH_NUM = 1
+	   J = 1
+	   DO WHILE (CLI$GET_VALUE('SEARCH_STRING',SEARCH_STRING(J:),
+     &	    SEARCH_LEN(SEARCH_NUM)).NE.%LOC(CLI$_ABSENT))
+	      J = J + SEARCH_LEN(SEARCH_NUM)
+	      SEARCH_NUM = SEARCH_NUM + 1
+	   END DO
+           IF (SEARCH_NUM.GT.1) SEARCH_NUM = SEARCH_NUM - 1
+	   NFOLDER = 1
+	ELSE
+	   IF (NFOLDER.EQ.0) NFOLDER = 1
+	   SEARCH_STRING = ' '
+	END IF
+
+	IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	   CALL INIT_QUEUE(SCRATCH_F1,FOLDER1_NAME)
+	   SCRATCH_F = SCRATCH_F1
+	   NFOLDER = 0
+	END IF
+
+	DO WHILE (CLI$GET_VALUE('SELECT_FOLDER',FOLDER1_NAME)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified folders
+	   IF (TRIM(FOLDER1_NAME).EQ.0) FOLDER1_NAME = FOLDER_NAME
+	   NFOLDER = NFOLDER + 1
+	   CALL WRITE_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,FOLDER1_NAME)
+	END DO
+
+	IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	   SCRATCH_F = SCRATCH_F1
+	   NFOLDER = NFOLDER + 1
+	END IF
+
+	IF (CLI$PRESENT('GROUP')) THEN
+	   CALL INIT_QUEUE(SCRATCH_F1,GROUP)
+	   SCRATCH_F = SCRATCH_F1
+	   NFOLDER = 0
+	   NGROUP = 0
+	   DO WHILE (CLI$GET_VALUE('GROUP',GROUP)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified folders
+	      NGROUP = NGROUP + 1
+	      CALL LOWERCASE(GROUP)
+	      CALL WRITE_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	   END DO
+	   SCRATCH_F = SCRATCH_F1
+	   CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+	   GLEN = TRIM(GROUP)
+	   FEEDBACK = CLI$PRESENT('FEEDBACK')
+	   NFOLDER = -1000
+	   OLD_BUFFER = ' '
+	END IF
+
+	START_BULL = BULL_POINT
+
+	IF (CLI$PRESENT('START')) THEN		! Starting message specified
+	   IF (CLI$GET_VALUE('START',BULL_PARAMETER,LEN_P)) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) START_BULL
+	   END IF
+	   IF (.NOT.CLI$PRESENT('REPLY')) START_BULL = START_BULL - 1
+	END IF
+
+	MATCH_MODE = 0
+	IF (CLI$PRESENT('MATCH')) THEN 
+	   CALL CLI$GET_VALUE('MATCH',BULL_PARAMETER,LEN_P)
+           IF (BULL_PARAMETER(:LEN_P).EQ.'AND') MATCH_MODE = 1
+           IF (BULL_PARAMETER(:LEN_P).EQ.'XOR') MATCH_MODE = 2
+	END IF
+
+	IF (NFOLDER.NE.0) FOUND = 0
+
+	CHANGE = .FALSE.
+	IF (CLI$PRESENT('REPLY').OR.
+     &	    TRIM(SEARCH_STRING).GT.0) THEN 
+	   REVERSE = CLI$PRESENT('REVERSE')
+	ELSE
+	   REVERSE = .FALSE.
+	END IF
+
+	DO WHILE (NFOLDER.NE.0.AND.FOUND.LE.0.AND.FOUND.GT.-3)
+	   IF ((NFOLDER.GT.0.AND.(.NOT.CLI$PRESENT('SELECT_FOLDER').OR.
+     &	       SCRATCH_F.NE.SCRATCH_F1)).OR.
+     &	       (NFOLDER.LT.0.AND.OLD_BUFFER.NE.' '))
+     &	      CALL GET_SEARCH(FOUND,SEARCH_STRING,SEARCH_NUM,
+     &		SEARCH_LEN,MATCH_MODE,START_BULL,
+     &		REVERSE,CLI$PRESENT('SUBJECT')
+     &	        .OR.CLI$PRESENT('NOREPLIES'),
+     &		CLI$PRESENT('REPLY'),.TRUE.,CLI$PRESENT('START'),
+     &		CLI$PRESENT('FROM'),CLI$PRESENT('NEGATED')
+     &	        .OR.CLI$PRESENT('NOREPLIES'),CHANGE)
+	   IF (FOUND.LE.0.AND.FOUND.GE.-2) THEN
+	      NFOLDER = NFOLDER - 1
+	      IF (NFOLDER.GT.0) THEN
+	         CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,FOLDER1_NAME)
+		 OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	         FOLDER_NUMBER = -1
+		 IER = 0
+		 DO WHILE (.NOT.IER.AND.NFOLDER.GT.0)
+		    FOLDER1 = FOLDER1_NAME
+	            CALL SELECT_FOLDER(.FALSE.,IER)
+		    IF (.NOT.IER) THEN
+		       FOLDER_NUMBER = OLD_FOLDER_NUMBER
+		       WRITE (6,'('' ERROR: Cannot find folder '',A,
+     &			  ''.'')') FOLDER1_NAME(:TRIM(FOLDER1_NAME))
+	               CALL GET_INPUT_PROMPT(FOLDER1_NAME,ILEN,
+     &		       'Type new folder name or hit RETURN to continue: ')
+	               IF (ILEN.LE.0.AND.NFOLDER.GT.0) THEN
+		          NFOLDER = NFOLDER - 1
+	                  CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,
+     &				          FOLDER1_NAME)
+		       END IF
+		    ELSE
+	   	       IF (FEEDBACK) WRITE (6,'('' Searching '',A)')
+     &				FOLDER_NAME(:TRIM(FOLDER_NAME))
+		       CHANGE = .TRUE.
+	      	       START_BULL = 0
+		       IF (REVERSE) START_BULL = NBULL - 1
+		    END IF
+		 END DO
+	      ELSE IF (NFOLDER.LT.0) THEN
+		 NFOLDER = NFOLDER + 1
+		 GFOUND = .FALSE.
+	       	 CALL DECLARE_CTRLC_AST
+		 DO WHILE (.NOT.GFOUND.AND.NGROUP.GT.0.AND.FLAG.NE.1)
+	            CALL OPEN_BULLNEWS_SHARED
+		    CALL READ_FOLDER_FILE_KEYNUM_TEMP(-NFOLDER,IER)
+		    IF (IER.EQ.0) 
+     &		       CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+		    DO WHILE (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10))
+		       CALL READ_FOLDER_FILE_TEMP(IER)
+	            END DO
+		    IF (IER.NE.0) NFOLDER = 0
+		    DO WHILE (.NOT.GFOUND.AND.NFOLDER.NE.0.AND.FLAG.NE.1)
+	               CALL GET_NEXT_GROUP(.TRUE.,GROUP,GLEN,GFOUND,
+     &				        .FALSE.,STAT,IER,.TRUE.)
+		       IF (GFOUND) THEN
+	      	          START_BULL = 0
+		          IF (REVERSE) START_BULL = NBULL - 1
+		          OLD_FOLDER_NUMBER = FOLDER_NUMBER
+	                  FOLDER_NUMBER = -1
+		          FOLDER1 = FOLDER1_DESCRIP(
+     &		          		:INDEX(FOLDER1_DESCRIP,' '))
+	                  CALL SELECT_FOLDER(.FALSE.,IER)
+		          IF (.NOT.IER) THEN
+		             FOLDER_NUMBER = OLD_FOLDER_NUMBER
+		             GFOUND = .FALSE.
+		          ELSE
+	   	             IF (FEEDBACK) WRITE (6,'('' Searching '',A)')
+     &		          		FOLDER_NAME(:TRIM(FOLDER_NAME))
+		             CHANGE = .TRUE.
+		             NFOLDER = -FOLDER_NUMBER
+		          END IF
+		       ELSE
+		          NFOLDER = 0
+		       END IF
+		    END DO
+		    CALL CLOSE_BULLFOLDER
+		    IF (NFOLDER.EQ.0) NGROUP = NGROUP - 1
+		    IF (NFOLDER.EQ.0.AND.NGROUP.GT.0) THEN
+		       CALL READ_QUEUE(%VAL(SCRATCH_F),SCRATCH_F,GROUP)
+		       GLEN = TRIM(GROUP)
+		       NFOLDER = -1000
+		    END IF
+	         END DO
+		 IF (FLAG.EQ.1) THEN
+		    WRITE (6,'('' Search aborted.'')')
+		    NFOLDER = 0
+		 END IF
+	     	 CALL CANCEL_CTRLC_AST
+	      END IF
+	   END IF
+	END DO
+
+	IF (FOUND.EQ.-3) FOUND = 0
+
+	IF (FOUND.GT.0) THEN
+	   BULL_POINT = FOUND - 1
+	   CALL READ_MSG(READ_COUNT,BULL_POINT+1) ! Read next bulletin
+	ELSE IF (FOUND.EQ.0) THEN
+	   IF (CHANGE) THEN 
+  	      WRITE (6,'('' No matches found in current folder: '',A)')
+     &			FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   ELSE
+  	      WRITE (6,'('' No matches found.'')')
+	   END IF
+	ELSE IF (FOUND.EQ.-2) THEN
+	   IF (CHANGE) THEN 
+	      WRITE (6,'('' ERROR: No more messages in current folder: ''
+     &			,A)') FOLDER_NAME(:TRIM(FOLDER_NAME))
+	   ELSE
+	      WRITE (6,'('' ERROR: No more messages.'')')
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_SEARCH(FOUND,SEARCH_STRING,SEARCH_NUM,SEARCH_LEN,
+     &	        MATCH_INPUT,START_BULL,REVERSE,SUBJECT,REPLY,FILES,START,
+     &		FROM_SEARCH,NEGATE,CHANGE)
+C
+C  SUBROUTINE GET_SEARCH
+C
+C  FUNCTION: Search for bulletin with specified string
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) SEARCH_STRING
+
+	DIMENSION SEARCH_LEN(1)
+	DIMENSION MATCH_FOUND(10)
+
+	CHARACTER*132 SAVE_STRING
+	DATA SAVE_STRING/' '/
+
+	COMMON /NEWGROUP/ NEWGROUP
+
+	COMMON /NEXT/ NEXT
+	LOGICAL NEXT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	CHARACTER*4 SAVECMD 
+
+	CHARACTER*128 DESCRIP1
+
+	FOUND = -1
+
+	CALL DISABLE_CTRL
+
+	CALL DECLARE_CTRLC_AST
+
+	IF (TRIM(SEARCH_STRING).EQ.0) THEN
+	   IER1 = .FALSE.
+	ELSE
+	   IER1 = .TRUE.
+	END IF
+	
+	IF (.NOT.IER1.AND..NOT.REPLY.AND.
+     &      (SUBJECT.OR.SEARCH_MODE.NE.1)) THEN
+						! If no search string entered
+	   SEARCH_STRING = SAVE_STRING		! use saved search string
+	   IF (TRIM(SAVE_STRING).EQ.0) THEN
+	      WRITE (6,'('' No search string present.'')')
+	      CALL CANCEL_CTRLC_AST
+	      CALL ENABLE_CTRL
+	      RETURN
+	   END IF
+	   IF (STEP_BULL.EQ.-1) START_BULL = START_BULL - 2
+	ELSE IF (.NOT.IER1.AND.SEARCH_MODE.EQ.1.AND..NOT.REPLY) THEN
+	   SEARCH_STRING = SAVE_STRING		! use saved search string
+	   IF (STEP_BULL.EQ.-1) START_BULL = START_BULL - 2
+	END IF
+
+	IF (FILES) CALL OPEN_BULLDIR_SHARED
+
+	CALL READDIR(0,IER)
+
+	OLD_SEARCH_MODE = SEARCH_MODE
+	OLD_MATCH_MODE = MATCH_MODE
+
+	IF (IER1) THEN				! If string entered
+	   IF (SUBJECT) THEN
+	      SEARCH_MODE = 3
+	   ELSE IF (FROM_SEARCH) THEN    
+	      SEARCH_MODE = 4
+	   ELSE
+	      SEARCH_MODE = 2
+	   END IF
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	   OLD_REVERSE = REVERSE
+	ELSE IF (SUBJECT.AND.SEARCH_MODE.NE.3) THEN
+	   SEARCH_MODE = 3
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	ELSE IF (FROM_SEARCH.AND.SEARCH_MODE.NE.4) THEN
+	   SEARCH_MODE = 4
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	ELSE IF (REPLY) THEN
+	   OLD_REVERSE = REVERSE
+	   NEGATED = NEGATE
+	   MATCH_MODE = MATCH_INPUT
+	   CALL READDIR(BULL_POINT,IER)
+	   IF (BULL_POINT+1.NE.IER) THEN
+	      WRITE (6,'('' ERROR: No message being read.'')')
+	      IF (FILES) CALL CLOSE_BULLDIR
+	      CALL CANCEL_CTRLC_AST
+	      CALL ENABLE_CTRL
+	      RETURN
+	   ELSE
+	      SEARCH_MODE = 1
+	      SEARCH_STRING = DESCRIP
+	      IF (STREQ(DESCRIP(:4),'RE: ').AND.TRIM(DESCRIP).GE.
+     &		 LEN(DESCRIP)-1) THEN
+	       	 IF (FILES) CALL OPEN_BULLFIL_SHARED
+	         IF (REMOTE_SET) THEN
+		    CALL REMOTE_READ_MESSAGE(BULL_POINT,IER)
+	            IF (IER.GT.0) THEN
+	               CALL DISCONNECT_REMOTE
+		       GO TO 900
+	            ELSE
+	               CALL GET_REMOTE_MESSAGE(IER)
+		       IF (IER.GT.0) GO TO 900
+	            END IF
+	         END IF
+	         ILEN = LINE_LENGTH + 1
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	         IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	         END IF
+	         IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	            SEARCH_STRING = INPUT(11:)
+	            SEARCH_STRING = SEARCH_STRING(:LEN(DESCRIP))
+		 ELSE
+	            SEARCH_STRING = DESCRIP(5:)
+	         END IF
+	       	 IF (FILES) CALL CLOSE_BULLFIL
+	      ELSE IF (STREQ(DESCRIP(:4),'RE: ')) THEN 
+	         SEARCH_STRING = DESCRIP(5:)
+	      END IF
+	      SEARCH_LEN(1) = TRIM(SAVE_STRING)
+	      IF (REVERSE) START_BULL = START_BULL - 2
+	   END IF
+	ELSE
+	   SEARCH_NUM = OLD_SEARCH_NUM
+	   IF (SEARCH_LEN(1).EQ.0) SEARCH_LEN(1) = TRIM(SAVE_STRING)
+	   IF (OLD_REVERSE) THEN
+	      START_BULL = MIN(START_BULL,NBULL-1)
+	      END_BULL = 1
+	      STEP_BULL = -1
+	   ELSE
+	      END_BULL = NBULL
+	      STEP_BULL = 1
+	      START_BULL = MAX(0,START_BULL)
+	   END IF
+	END IF
+
+	OLD_SEARCH_NUM = SEARCH_NUM
+
+	SAVE_STRING = SEARCH_STRING
+
+	CALL STR$UPCASE(SEARCH_STRING,SEARCH_STRING)	! Make upper case
+
+	IF (IER1.OR.SEARCH_MODE.NE.OLD_SEARCH_MODE.OR.CHANGE.OR.
+     &	    MATCH_MODE.NE.OLD_MATCH_MODE.OR.REVERSE.OR.REPLY) THEN
+	   IF (.NOT.START.AND.SEARCH_MODE.NE.1) THEN  
+	      START_BULL = 0	! If starting message not specified, use first
+	      IF (REVERSE) START_BULL = NBULL - 1  ! or last
+	   END IF
+	   IF (REVERSE) THEN
+	      START_BULL = MIN(START_BULL,NBULL-1)
+	      END_BULL = 1
+	      STEP_BULL = -1
+	   ELSE
+	      END_BULL = NBULL
+	      STEP_BULL = 1
+	      START_BULL = MAX(0,START_BULL)
+	   END IF
+	END IF
+
+	IF ((START_BULL+1.GT.NBULL.AND.STEP_BULL.EQ.1).OR.
+     &	    (START_BULL+1.EQ.0)) THEN
+	   FOUND = -2
+	   IF (FILES) CALL CLOSE_BULLDIR
+	   CALL CANCEL_CTRLC_AST
+	   CALL ENABLE_CTRL
+	   SEARCH_STRING = ' '
+	   RETURN
+	END IF
+
+	IF (FILES) CALL OPEN_BULLFIL_SHARED
+
+	NEWGROUP = .TRUE.
+	NEXT = STEP_BULL.EQ.1
+	SAVECMD = INCMD(:4)
+	IF (STEP_BULL.EQ.-1) INCMD(:4) = 'BACK'
+
+	SAVE_BULL_SEARCH = 0
+	BULL_SEARCH = START_BULL+1
+	DO WHILE ((STEP_BULL.EQ.1.AND.BULL_SEARCH.LE.END_BULL).OR.
+     &		(STEP_BULL.EQ.-1.AND.BULL_SEARCH.GE.MAX(1,F_START)))
+	   CALL READDIR(BULL_SEARCH,IER)	! Get bulletin directory entry
+	   IF (READ_TAG) THEN
+	      IF (STEP_BULL.EQ.-1) THEN
+		 CALL GET_THIS_TAG(FOLDER_NUMBER,IER,BULL_SEARCH,DUMMY)
+	 	 IF (IER.NE.0) THEN
+		    CALL GET_PREVIOUS_TAG(FOLDER_NUMBER,IER,
+     &			BULL_SEARCH,DUMMY)
+		 END IF
+	      ELSE
+		 CALL GET_THIS_OR_NEXT_TAG(FOLDER_NUMBER,IER,
+     &			BULL_SEARCH,DUMMY)
+	      END IF
+	      IF (IER.EQ.0) THEN
+		 IER = BULL_SEARCH + 1
+	      ELSE
+		 GO TO 800
+	      END IF
+	   END IF
+	   IF (REMOTE_SET.EQ.3.AND.SAVE_BULL_SEARCH.EQ.BULL_SEARCH) GO TO 800
+	   SAVE_BULL_SEARCH = BULL_SEARCH
+	   IF (IER.EQ.BULL_SEARCH+1.AND.SEARCH_MODE.NE.2) THEN
+	      IF (SEARCH_MODE.EQ.4) THEN
+	         CALL STR$UPCASE(DESCRIP1,FROM)
+	      ELSE
+		 IF (LEN(DESCRIP).EQ.TRIM(DESCRIP)) THEN
+	            IF (REMOTE_SET) THEN
+		       CALL REMOTE_READ_MESSAGE(BULL_SEARCH,IER)
+	               IF (IER.GT.0) THEN
+	                  CALL DISCONNECT_REMOTE
+		          GO TO 900
+	               ELSE
+	                  CALL GET_REMOTE_MESSAGE(IER)
+		          IF (IER.GT.0) GO TO 900
+	               END IF
+	            END IF
+		    ILEN = LINE_LENGTH + 1
+		    CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+		       CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+		    END IF
+		    IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+		       DESCRIP1 = INPUT(7:)
+		    END IF
+	            CALL STR$UPCASE(DESCRIP1,DESCRIP1)
+		 ELSE
+	            CALL STR$UPCASE(DESCRIP1,DESCRIP)
+		 END IF
+	      END IF
+	      IF ((SEARCH_MODE.GE.3.AND.MATCH(DESCRIP1,SEARCH_STRING,
+     &		  SEARCH_LEN,SEARCH_NUM,MATCH_MODE)).OR.
+     &		  (SEARCH_MODE.EQ.1.AND.(DESCRIP1.EQ.SEARCH_STRING.OR.
+     &		  (TRIM(SEARCH_STRING).EQ.LEN(DESCRIP).AND.
+     &		   DESCRIP1(:LEN(DESCRIP)).EQ.SEARCH_STRING).OR.
+     &		   (STREQ(DESCRIP1(:4),'RE: ').AND.DESCRIP1(5:).EQ.
+     &		   SEARCH_STRING(:MIN(TRIM(SEARCH_STRING),LEN(DESCRIP1)-4))
+     &		   )))) THEN
+                 IF (.NOT.NEGATED) THEN
+		    FOUND = BULL_SEARCH
+		    GO TO 900
+	         END IF   
+	      ELSE IF (FLAG.EQ.1) THEN
+		 WRITE (6,'('' Search aborted.'')')
+		 FOUND = -3
+		 GO TO 900
+              ELSE IF (NEGATED) THEN 
+                 FOUND = BULL_SEARCH
+                 GO TO 900
+	      END IF
+	   END IF
+	   IF (IER.EQ.BULL_SEARCH+1.AND.SEARCH_MODE.EQ.2) THEN
+	      IF (REMOTE_SET) THEN
+		 CALL REMOTE_READ_MESSAGE(BULL_SEARCH,IER)
+	         IF (IER.GT.0) THEN
+	            CALL DISCONNECT_REMOTE
+		    GO TO 900
+	         ELSE
+	            CALL GET_REMOTE_MESSAGE(IER)
+		    IF (IER.GT.0) GO TO 900
+	         END IF
+	      END IF
+	      ILEN = LINE_LENGTH + 1
+              MATCHES = 0
+	      DO I=1,SEARCH_NUM
+		 MATCH_FOUND(I) = .FALSE.
+	      END DO
+	      DO WHILE (ILEN.GT.0)
+	         CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	         CALL STR$UPCASE(INPUT,INPUT)	! Make upper case
+		 J = 1
+		 DO I=1,SEARCH_NUM
+		    IF (.NOT.MATCH_FOUND(I)) THEN
+		       MATCH_FOUND(I) = INDEX(INPUT,
+     &				SEARCH_STRING(J:J+SEARCH_LEN(I)-1)).GT.0
+		       IF (MATCH_FOUND(I)) MATCHES = MATCHES + 1
+		    END IF
+		    J = J + SEARCH_LEN(I)
+	         END DO
+		 IF ((MATCHES.GT.0.AND.MATCH_MODE.EQ.0).OR.
+     &	             (MATCHES.EQ.SEARCH_NUM.AND.MATCH_MODE.EQ.1)) THEN
+		    FOUND = BULL_SEARCH
+		    IF (.NOT.NEGATED) GO TO 900
+		 ELSE IF (FLAG.EQ.1) THEN
+		    WRITE (6,'('' Search aborted.'')')
+		    FOUND = -3
+		    GO TO 900
+		 END IF
+	      END DO
+	      IF (MATCHES.EQ.1.AND.MATCH_MODE.EQ.2) THEN
+		 FOUND = BULL_SEARCH
+		 IF (.NOT.NEGATED) GO TO 900
+              END IF
+              IF (NEGATED) THEN 
+                 IF (FOUND.EQ.-1) THEN
+                    FOUND = BULL_SEARCH
+ 		    GO TO 900
+		 ELSE
+		    FOUND = -1
+	         END IF
+	      END IF
+	   END IF
+	   BULL_SEARCH = BULL_SEARCH + STEP_BULL
+	END DO
+
+800	FOUND = 0
+
+900	IF (FOUND.LE.0.AND.REMOTE_SET.EQ.3) THEN
+	   NEXT = .FALSE.
+	   CALL READDIR(BULL_POINT,IER)
+	   CALL REMOTE_READ_MESSAGE(BULL_POINT,IER)
+	   IF (IER.GT.0) THEN
+	      CALL DISCONNECT_REMOTE
+	   ELSE
+	      CALL GET_REMOTE_MESSAGE(IER)
+	   END IF
+	END IF
+	IF (FILES) CALL CLOSE_BULLFIL		! End of bulletin file read
+	IF (FILES) CALL CLOSE_BULLDIR
+	CALL CANCEL_CTRLC_AST
+	CALL ENABLE_CTRL
+
+	IF (.NOT.IER1) SEARCH_STRING = ' '
+	NEXT = .FALSE.
+	IF (STEP_BULL.EQ.-1) INCMD(:4) = SAVECMD
+
+	RETURN
+	END
+ 
+
+
+
+        LOGICAL FUNCTION MATCH(INPUT,SEARCH_STRING,SEARCH_LEN,
+     &                         SEARCH_NUM,MATCH_MODE)
+
+        IMPLICIT INTEGER (A - Z)
+
+	DIMENSION SEARCH_LEN(1)
+
+        CHARACTER*(*) INPUT,SEARCH_STRING
+ 
+        OLD_MATCH = .FALSE.
+
+	J = 1
+
+	DO I=1,SEARCH_NUM
+	   MATCH = INDEX(INPUT,SEARCH_STRING(J:J+SEARCH_LEN(I)-1)).GT.0
+           IF (MATCH.AND.MATCH_MODE.EQ.0) RETURN
+           IF (.NOT.MATCH.AND.MATCH_MODE.EQ.1) RETURN
+           IF (OLD_MATCH.AND.MATCH.AND.MATCH_MODE.EQ.2) THEN
+              MATCH = .FALSE.
+	      RETURN
+           END IF
+	   J = J + SEARCH_LEN(I)
+	END DO
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UNDELETE
+C
+C  SUBROUTINE UNDELETE
+C
+C  FUNCTION: Undeletes deleted message.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	EXTERNAL CLI$_ABSENT
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   WRITE (6,'('' Cannot UNDELETE messages in this folder.'')')
+	   RETURN
+	END IF
+C
+C  Get the bulletin number to be undeleted.
+C
+
+	IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
+	IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Was bulletin specified?
+	   DECODE(LEN_P,5,BULL_PARAMETER,ERR=920) BULL_DELETE	! Yes
+5	   FORMAT(I<LEN_P>)
+	ELSE IF (BULL_POINT.EQ.0) THEN	! No.  Have we just read a bulletin?
+	   GO TO 910			! No, then error.
+	ELSE
+	   BULL_DELETE = BULL_POINT	! Delete the file we are reading
+	END IF
+
+	IF (BULL_DELETE.LE.0) GO TO 920
+
+C
+C  Check to see if specified bulletin is present, and if the user
+C  is permitted to delete the bulletin.
+C
+
+	CALL OPEN_BULLDIR
+
+	CALL READDIR(BULL_DELETE,IER)	! Get info for specified bulletin
+
+	IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	   WRITE(6,1030)	! If not, then error out
+	   GOTO 100
+	END IF
+
+	IF (USERNAME.NE.FROM) THEN	! If doesn't match owner of bulletin,
+	   IF ((.NOT.SETPRV_PRIV().AND..NOT.FOLDER_SET).OR.	! Privileges or
+     &	       (.NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)
+     &		.AND.FOLDER_SET)) THEN				! folder owner?
+	      WRITE(6,1040)		! Then error out.
+	      GO TO 100
+	   ELSE
+	      CALL READDIR(BULL_DELETE,IER) ! Get info for specified bulletin
+	      IF (IER.NE.BULL_DELETE+1) THEN	! Was bulletin found?
+	         WRITE(6,1030)		! If not, then error out
+	         GOTO 100
+	      END IF
+	   END IF
+	END IF
+
+	IF ((SYSTEM.AND.7).LE.1) THEN	! General or System message
+	   IF (EXDATE(8:11).LT.'1900') EXDATE(8:9) = '19'
+	   IF (EXDATE(8:11).LT.'1995') EXDATE(8:9) = '20'
+	ELSE				! Permanent or Shutdown
+	   IF (EXDATE(2:2).EQ.'-') THEN
+	      EXDATE = EXDATE(:6)//'21'//EXDATE(9:)
+	   ELSE
+	      EXDATE = EXDATE(:7)//'21'//EXDATE(10:)
+	   END IF
+	END IF
+
+	IF (.NOT.REMOTE_SET) THEN
+	   CALL WRITEDIR(BULL_DELETE,IER)	! Update message expiration date
+	   WRITE (6,'('' Message was undeleted.'')')
+	ELSE
+	   WRITE (REMOTE_UNIT,'(5A)',IOSTAT=IER)
+     &      11,BULL_DELETE,DESCRIP,EXDATE,EXTIME
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (I.NE.LEN(FOLDER1_COM)) THEN
+		 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      ELSE
+	         WRITE (6,'('' Message was undeleted.'')')
+	      END IF
+	   ELSE
+	      CALL DISCONNECT_REMOTE
+	   END IF
+	END IF
+
+100	CALL CLOSE_BULLDIR
+
+900	RETURN
+
+910	WRITE(6,1010)
+	GO TO 900
+
+920	WRITE(6,1020)
+	GO TO 900
+
+1010	FORMAT(' ERROR: You are not reading any message.')
+1020	FORMAT(' ERROR: Specified message number has incorrect format.')
+1030	FORMAT(' ERROR: Specified message was not found.')
+1040	FORMAT(' ERROR: Message was not undeleted. Not owned by you.')
+
+	END
+
+
+
+
+	SUBROUTINE ADD_PROTOCOL(INPUT,ILEN)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLNEWS.INC'
+
+	CHARACTER*20 MAIL_PROTOCOL
+
+	CHARACTER*(*) INPUT
+
+	CHARACTER*256 INPUT_OUT
+	CHARACTER*128 TEMP
+
+	INPUT_OUT = ' '
+
+	I = 0
+
+	DO WHILE (I.LT.TRIM(INPUT))
+	   INPUT = INPUT(I+1:)
+	   IF (I.GT.0) INPUT_OUT = INPUT_OUT(:TRIM(INPUT_OUT))//','
+	   I = MINGT0(INDEX(INPUT,','),TRIM(INPUT)+1)
+	   IF (INDEX(INPUT,',').EQ.I.AND.INDEX(INPUT(:I),'@').EQ.0)
+     &		I = TRIM(INPUT)+1
+	   TEMP = INPUT(:I-1)
+	   CALL ADD_PROTOCOL_SUB(TEMP)
+	   INPUT_OUT = INPUT_OUT(:TRIM(INPUT_OUT))//TEMP(:TRIM(TEMP))
+	END DO
+
+	INPUT = INPUT_OUT
+
+	IF (ILEN.NE.0) ILEN = TRIM(INPUT)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ADD_PROTOCOL_SUB(INPUT)
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLNEWS.INC'
+
+	CHARACTER*20 MAIL_PROTOCOL
+
+	CHARACTER*(*) INPUT
+
+	DATA LMAIL/0/
+
+	IF (LMAIL.EQ.-1) RETURN
+
+	IF (INDEX(INPUT,'@').EQ.0.OR.INDEX(INPUT,'%"').GT.0) RETURN
+
+	I = INDEX(INPUT,'<')
+	IF (I.GT.0.AND.INDEX(INPUT(I+1:),'@').GT.0) THEN ! Name may be of form
+	   INPUT = INPUT(INDEX(INPUT,'<')+1:INDEX(INPUT,'>')-1)
+						! personal-name <net-name>
+	END IF
+
+	IF (LMAIL.EQ.0) THEN
+	   IF (.NOT.SYS_TRNLNM('BULL_NEWS_MAILER',MAIL_PROTOCOL)) THEN
+	      MAIL_PROTOCOL = MAILER
+	   END IF
+	   LMAIL = TRIM(MAIL_PROTOCOL)
+	   IF (LMAIL.GT.0.AND.MAIL_PROTOCOL(LMAIL:LMAIL).NE.'%') THEN
+	      MAIL_PROTOCOL = MAIL_PROTOCOL(:LMAIL)//'%'
+	      LMAIL = LMAIL + 1
+	   END IF
+	   IF (LMAIL.EQ.0) THEN
+	      LMAIL = -1
+	      RETURN
+	   END IF
+	END IF
+
+	I = INDEX(INPUT,'@')
+	IF (I.GT.0) THEN
+	   INPUT = INPUT(:INDEX(INPUT(I:),' ')+I-2)
+	   IF (INDEX(INPUT(I:),'(').GT.0)
+     &		INPUT = INPUT(:INDEX(INPUT(I:),'(')+I-2)
+	END IF
+
+	INPUT = MAIL_PROTOCOL(:LMAIL)//'"'//INPUT(:TRIM(INPUT))//'"'
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin3.for b/decus/vmslt98a/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..109b5add81c86ce51fb3fb3b0e512486060f751c
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin3.for
@@ -0,0 +1,2510 @@
+C
+C  BULLETIN3.FOR, Version 12/4/97
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE UPDATE
+C
+C  SUBROUTINE UPDATE
+C
+C  FUNCTION:  Searches for bulletins that have expired and deletes them.
+C
+C  NOTE:  Assumes directory file is already opened.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	CHARACTER*12 TEMP_DATE,TEMP_EXDATE,TEMP_NOSYSDATE
+	CHARACTER*12 TEMP_TIME,TEMP_EXTIME,TEMP_NOSYSTIME
+
+	IF (REMOTE_SET.AND.
+     &		NODE_AREA.GT.0.AND.BTEST(FOLDER_FLAG,2)) THEN
+	   CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	END IF
+
+	IF (TEST_BULLCP().OR.REMOTE_SET) RETURN
+					! BULLCP cleans up expired bulletins
+
+	ENTRY UPDATE_ALWAYS		! Entry to skip BULLCP test
+
+	TEMP_EXDATE = '5-NOV-2100'  ! If a bulletin gets deleted, and there are
+	TEMP_EXTIME = '00:00:00.00' ! are no more bulletins, this is the value
+				    ! assigned to the latest expiration date
+
+	TEMP_DATE = '5-NOV-1956' 	! Storage for computing newest
+	TEMP_TIME = '00:00:00.00'	! bulletin date if deletion occurs
+
+	TEMP_NOSYSDATE = '5-NOV-1956' 	! Storage for computing newest
+	TEMP_NOSYSTIME = '00:00:00.00'	! non-system bulletin date
+
+	BULL_ENTRY = 1				! Init bulletin pointer
+	UPDATE_DONE = 0			! Flag showing bull has been deleted
+
+	NEW_SHUTDOWN = 0
+	OLD_SHUTDOWN = SHUTDOWN
+
+	DO WHILE (UPDATE_DONE.GE.0)
+	   CALL READDIR(BULL_ENTRY,IER)		! Get next directory entry
+	   IF (IER.EQ.BULL_ENTRY) GO TO 100	! ERROR: Not found
+	   IF ((SYSTEM.AND.7).LE.3.OR.(OLD_SHUTDOWN.EQ.0
+						! If not shutdown, or time
+     &	     .AND.(SYSTEM.AND.4).EQ.4)) THEN	! to delete shutdowns?
+	    IF ((SYSTEM.AND.4).EQ.4) THEN	! Shutdown bulletin?
+	       IF (NODE_AREA.GT.0) THEN
+	          READ (EXTIME(1:2),'(I2)') I
+	          READ (EXTIME(4:5),'(I2)') NODE_NUMBER_MSG
+		  NODE_NUMBER_MSG = NODE_NUMBER_MSG + I*60
+	          READ (EXTIME(7:8),'(I2)') I
+	          READ (EXTIME(10:11),'(I2)') NODE_AREA_MSG
+		  NODE_AREA_MSG = NODE_AREA_MSG + I*60
+	          IF (NODE_NUMBER_MSG.EQ.NODE_NUMBER.AND.
+     &		      NODE_AREA_MSG.EQ.NODE_AREA) THEN
+		     DIFF = 0
+		  ELSE
+		     DIFF = 1
+	             NEW_SHUTDOWN = NEW_SHUTDOWN + 1
+		  END IF
+	       END IF
+	    ELSE
+	       DIFF = COMPARE_DATE(EXDATE,' ')	! Has expiration date passed?
+	       IF (DIFF.EQ.0) DIFF = COMPARE_TIME(EXTIME,' ')
+	    END IF
+	    IF (DIFF.LE.0) THEN			! If so then delete bulletin
+	      CALL DELETE_ENTRY(BULL_ENTRY)	! Delete bulletin entry
+	      IF (UPDATE_DONE.EQ.0) THEN	! If this is first deleted file
+	         UPDATE_DONE = BULL_ENTRY	! store it to use for reordering
+	      END IF				! directory file.
+	    ELSE IF ((SYSTEM.AND.7).LE.3) THEN	! Expiration date hasn't passed
+		! If a bulletin is deleted, we'll have to update the latest
+		! expiration date. The following does that.
+	      DIFF = COMPARE_DATE(EXDATE,TEMP_EXDATE)
+	      IF (DIFF.LT.0.OR.(DIFF.EQ.0.AND.
+     &		COMPARE_TIME(EXTIME,TEMP_EXTIME).LT.0)) THEN
+	         TEMP_EXDATE = EXDATE		! If this is the latest exp
+	         TEMP_EXTIME = EXTIME		! date seen so far, save it.
+	      END IF
+	      TEMP_DATE = DATE			! Keep date after search
+	      TEMP_TIME = TIME			! we have the last message date
+	      IF (.NOT.BTEST(SYSTEM,0)) THEN
+		 TEMP_NOSYSDATE = DATE
+		 TEMP_NOSYSTIME = TIME
+	      END IF
+	    END IF
+	   ELSE
+	      TEMP_DATE = DATE
+	      TEMP_TIME = TIME
+	      IF (.NOT.BTEST(SYSTEM,0)) THEN
+		 TEMP_NOSYSDATE = DATE
+		 TEMP_NOSYSTIME = TIME
+	      END IF
+	   END IF
+	   BULL_ENTRY = BULL_ENTRY + 1
+	END DO
+
+100	IF (UPDATE_DONE.GT.0) THEN		! Reorder directory file
+	   CALL CLEANUP_DIRFILE(UPDATE_DONE)	! due to deleted entries
+	END IF
+
+	DATE = NEWEST_DATE
+	TIME = NEWEST_TIME
+	CALL READDIR(0,IER)
+	SHUTDOWN = NEW_SHUTDOWN
+	NEWEST_EXDATE = TEMP_EXDATE
+	DIFF = COMPARE_DATE(NEWEST_EXDATE,' ')
+	IF (DIFF.GT.20*356) NEWEST_EXDATE = '5-NOV-2100'
+	NEWEST_EXTIME = TEMP_EXTIME
+	NEWEST_DATE = TEMP_DATE
+	NEWEST_TIME = TEMP_TIME
+	CALL WRITEDIR(0,IER)
+	SYSTEM = 0			! Updating last non-system date/time
+	NEWEST_DATE = TEMP_NOSYSDATE
+	NEWEST_TIME = TEMP_NOSYSTIME
+	CALL UPDATE_FOLDER
+	SYSTEM = 1			! Now update latest date/time
+	NEWEST_DATE = TEMP_DATE
+	NEWEST_TIME = TEMP_TIME
+	CALL UPDATE_FOLDER
+
+	IF (NODE_AREA.GT.0.AND.BTEST(FOLDER_FLAG,2)) THEN ! Shutdowns deleted?
+	   CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)		  ! Save that info
+	END IF
+
+C
+C  If newest message date has been changed, must change it in BULLUSER.DAT
+C  and also see if it affects notification of new messages to users
+C
+	IF (TEMP_DATE.NE.DATE.OR.TEMP_TIME.NE.TIME) THEN
+	   CALL UPDATE_LOGIN(.FALSE.)
+	END IF
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE UPDATE_READ(USERFILE_OPEN)
+C
+C  SUBROUTINE UPDATE_READ
+C
+C  FUNCTION:
+C	Store the latest date that user has used the BULLETIN facility.
+C	If new bulletins have been added, alert user of the fact.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($PRVDEF)'
+
+	CHARACTER TODAY*24
+
+	DIMENSION TODAY_BTIM(2),READ_BTIM_SAVE(2)
+
+	LOGICAL MODIFY_SYSTEM /.TRUE./
+
+C
+C  Update user's latest read time in his entry in BULLUSER.DAT.
+C
+	IF (.NOT.USERFILE_OPEN) THEN
+	   CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+	END IF
+
+	CALL READ_USER_FILE_HEADER(IER)
+
+	IF (IER.NE.0) THEN			! If header not present, exit
+	   IF (.NOT.USERFILE_OPEN) CALL CLOSE_BULLUSER
+	   RETURN
+	ELSE IF (USERPRIV(1).EQ.-1.AND.USERPRIV(2).EQ.-1) THEN
+						! If header present, but no
+	   DO I=1,FLONG				! SET_FLAG and NOTIFY_FLAG
+	      SET_FLAG_DEF(I) = 0		! information, write default
+	      NOTIFY_FLAG_DEF(I) = 0		! flags.
+	      BRIEF_FLAG_DEF(I) = 0
+	   END DO
+	   SET_FLAG_DEF(1) = 1
+	   USERPRIV(1) = PRV$M_OPER.OR.PRV$M_CMKRNL.OR.PRV$M_SETPRV
+	   USERPRIV(2) = 0
+	   REWRITE (4) USER_HEADER
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get today's time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	UNLOCK 4
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER1)
+
+	IF (IER1.EQ.0) THEN			! If entry found, update it
+	   IF (USERFILE_OPEN.EQ.0) THEN
+	      READ_BTIM_SAVE(1) = READ_BTIM(1)
+	      READ_BTIM_SAVE(2) = READ_BTIM(2)
+	      READ_BTIM(1) = TODAY_BTIM(1)
+	      READ_BTIM(2) = TODAY_BTIM(2)
+	      REWRITE (4) USER_ENTRY
+     	      READ_BTIM(1) = READ_BTIM_SAVE(1)
+	      READ_BTIM(2) = READ_BTIM_SAVE(2)
+	   END IF
+	ELSE					! If no entry create a new entry
+	   NEW_FLAG(1) = 143
+	   NEW_FLAG(2) = 0
+	   LOGIN_BTIM(1) = TODAY_BTIM(1)
+	   LOGIN_BTIM(2) = TODAY_BTIM(2)
+	   READ_BTIM(1) = TODAY_BTIM(1)
+	   READ_BTIM(2) = TODAY_BTIM(2)
+	   CALL WRITE_USER_FILE_NEW(IER)
+	END IF
+
+	IF (MODIFY_SYSTEM) THEN
+	   CALL MODIFY_SYSTEM_LIST(1)
+	   MODIFY_SYSTEM = .FALSE.
+	END IF
+
+	IF (.NOT.USERFILE_OPEN) THEN
+	   CALL CLOSE_BULLUSER			! All finished with BULLUSER
+	END IF
+
+	RETURN					! to go home...
+
+	END
+
+
+
+
+	SUBROUTINE FIND_NEWEST_BULL
+C
+C  SUBROUTINE FIND_NEWEST_BULL
+C
+C	If new bulletins have been added, alert user of the fact and
+C	set the next bulletin to be read to the first new bulletin.
+C
+C  OUTPUTS:
+C	BULL_POINT  -  If -1, no new bulletins to read, else there are.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /POINT/ BULL_POINT
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INTEGER DIR_BTIM(2)
+
+C
+C  Now see if bulletins have been added since the user's previous
+C  read time.  If they have, then search for the first new bulletin.
+C  Ignore new bulletins that are owned by the user or system notices
+C  that have not been added since the user has logged in.
+C
+	BULL_POINT = -1				! Init bulletin pointer
+
+	CALL OPEN_BULLDIR_SHARED		! Yep, so get directory file
+	CALL READDIR(0,IER)			! Get # bulletins from header
+	IF (IER.EQ.1) THEN
+	   CALL GET_NEWEST_MSG(LAST_READ_BTIM(1,FOLDER_NUMBER+1),START)
+	   IF (START.LE.0) THEN
+	      BULL_POINT = START
+	      CALL CLOSE_BULLDIR
+	      RETURN
+	   END IF
+	   DO WHILE (START.LE.NBULL.AND.(FROM.EQ.USERNAME.OR.SYSTEM))
+	      IF (FROM.NE.USERNAME) THEN	! Ignore bull if owner is user
+	         IF (SYSTEM) THEN		! If system bulletin
+	            CALL SYS_BINTIM(DATE//' '//TIME,DIR_BTIM)
+	            DIFF = COMPARE_BTIM(LOGIN_BTIM,DIR_BTIM)
+		    IF (DIFF.GT.0) THEN
+		       START = START + 1
+	               CALL READDIR(START,IER)
+		    ELSE			! SYSTEM bulletin was not seen
+		       SYSTEM = 0		! so force exit to read it.
+		    END IF
+	         END IF
+	      ELSE
+		 START = START + 1
+		 CALL READDIR(START,IER)
+		 IF (IER.NE.START+1) START = NBULL + 1
+	      END IF
+	   END DO
+	   IF (START.LE.NBULL) BULL_POINT = START - 1
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_EXPIRED(EXPDAT,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*24 EXPDAT
+	CHARACTER*24 TODAY
+
+	DIMENSION EXTIME_BIN(2),NOW(2)
+
+	EXTERNAL CLI$_ABSENT
+
+	IER = SYS$ASCTIM(,TODAY,,)		! Get today's date
+
+	IERC = CLI$GET_VALUE('EXPIRATION',EXPDAT,ILEN)
+
+	PROMPT = .TRUE.
+
+	EXPIRE_LIMIT = F_EXPIRE_LIMIT
+	IF (REMOTE_SET.EQ.4.AND.EXPIRE_LIMIT.EQ.0)
+     &	   EXPIRE_LIMIT = NEWS_EXPIRE_LIMIT_DEFAULT
+
+5	IF (PROMPT) THEN
+	   IF (IERC.NE.%LOC(CLI$_ABSENT)) THEN	! Was value specified?
+	      PROMPT = .FALSE.
+	   ELSE
+	      DEFAULT_EXPIRE = FOLDER_BBEXPIRE
+	      IF (REMOTE_SET.EQ.4.AND.DEFAULT_EXPIRE.EQ.0)
+     &		 DEFAULT_EXPIRE = NEWS_EXPIRE_DEFAULT
+	      IF ((DEFAULT_EXPIRE.GT.EXPIRE_LIMIT.OR.DEFAULT_EXPIRE
+     &		  .EQ.0).AND.EXPIRE_LIMIT.GT.0.AND..NOT.
+     &	          FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+		 DEFAULT_EXPIRE = F_EXPIRE_LIMIT
+	      END IF
+	      IF (BTEST(FOLDER_FLAG,3).OR.
+     &		  REMOTE_SET.EQ.4) THEN		! NOPROMPT was set
+		 IF (DEFAULT_EXPIRE.LE.0) THEN		! If no expiration date
+	            SYSTEM = SYSTEM.OR.2		! make permanent
+	            EXPDAT = '5-NOV-2100 00:00:00.00'
+		 ELSE					! Else set expiration
+		    CALL GET_EXDATE(EXPDAT,DEFAULT_EXPIRE)
+		    EXPDAT = EXPDAT(:TRIM(EXPDAT))//' 00:00:00.00'
+		 END IF
+		 ILEN = TRIM(EXPDAT)
+	      ELSE
+		 IF (DEFAULT_EXPIRE.EQ.0) THEN	! Get expiration date
+	            WRITE(6,1030) TODAY(:INDEX(TODAY,'.')-4)
+		 ELSE IF (DEFAULT_EXPIRE.EQ.-1) THEN
+	            WRITE(6,1031) TODAY(:INDEX(TODAY,'.')-4)
+		 ELSE
+	            WRITE(6,1032) TODAY(:INDEX(TODAY,'.')-4),
+     &					DEFAULT_EXPIRE
+		 END IF
+		 WRITE (6,1035)
+	         CALL GET_LINE(EXPDAT,ILEN)	! Get EXPDAT line
+		 IF (ILEN.EQ.0.AND.DEFAULT_EXPIRE.NE.0) THEN
+		    IF (DEFAULT_EXPIRE.EQ.-1) THEN
+		       EXPDAT = '5-NOV-2100 00:00:00.00'
+		       SYSTEM = IBSET(SYSTEM,1)	! Indicate permanent message
+		    ELSE
+		       CALL GET_EXDATE(EXPDAT,DEFAULT_EXPIRE)
+		       EXPDAT = EXPDAT(:TRIM(EXPDAT))//' 00:00:00.00'
+		    END IF
+		    ILEN = TRIM(EXPDAT)
+		 END IF
+	      END IF
+	   END IF
+	ELSE
+	   RETURN
+	END IF
+
+	IF (ILEN.LE.0) THEN
+	   IER = 0
+	   RETURN
+	END IF
+
+	EXPDAT = EXPDAT(:ILEN)			! Change trailing zeros 2 spaces
+
+	IF (INDEX(EXPDAT,'-').EQ.0.AND.INDEX(EXPDAT,':').GT.0.AND.
+     &		INDEX(EXPDAT(:ILEN),' ').EQ.0) THEN	! Only time specified?
+	   EXPDAT = TODAY(:INDEX(TODAY(2:),' ')+1)//EXPDAT	! Add date
+	ELSE IF (INDEX(EXPDAT(6:),'-').EQ.0.AND.		! Date specified
+     &			INDEX(EXPDAT,'-').GT.0) THEN	! but no year?
+	   SPACE = INDEX(EXPDAT,' ') - 1			! Add year
+	   IF (SPACE.EQ.-1) SPACE = TRIM(EXPDAT) 
+	   YEAR = INDEX(TODAY(6:),'-')
+	   EXPDAT = EXPDAT(:SPACE)//TODAY(5+YEAR:9+YEAR)//EXPDAT(SPACE+1:)
+	END IF
+
+	CALL STR$UPCASE(EXPDAT,EXPDAT)		! Convert to upper case
+	IER = SYS_BINTIM(EXPDAT,EXTIME_BIN)
+	IF (IER.NE.1) THEN			! If not able to do so
+    	   WRITE(6,1040)			! tell user is wrong
+	   IER = 0				! Set error for return value
+	   GO TO 5				! Re-request date (if prompting)
+	END IF
+	IER = SYS$ASCTIM(TIMLEN,EXPDAT,EXTIME_BIN,)
+	IF (TIMLEN.EQ.16) THEN
+	   CALL SYS$GETTIM(NOW)
+	   CALL LIB$SUBX(NOW,EXTIME_BIN,EXTIME_BIN)
+	   IER = SYS$ASCTIM(TIMLEN,EXPDAT,EXTIME_BIN,)
+	END IF
+
+	IF (EXPDAT(2:2).EQ.'-') EXPDAT = '0'//EXPDAT
+	IER = COMPARE_DATE(EXPDAT(:11),TODAY(:11)) ! Compare date with today's
+	IF (IER.GT.EXPIRE_LIMIT.AND.EXPIRE_LIMIT.GT.0.AND.
+     &	    .NOT.FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	   WRITE(6,1050) EXPIRE_LIMIT		! Expiration date > limit
+	   IER = 0				! Set error for return value
+	   GO TO 5				! Re-request date (if prompting)
+	END IF
+	IF (IER.EQ.0) IER = COMPARE_TIME(EXPDAT(13:23),TODAY(13:23))
+	IF (IER.LE.0) THEN			! If expiration date not future
+	   WRITE(6,1045)			! tell user
+	   IER = 0				! Set error for return value
+	   GO TO 5				! Re-request date (if prompting)
+	END IF
+
+	IF (PROMPT) THEN
+	   IF (BTEST(SYSTEM,1)) THEN		! Permanent message
+	      WRITE (6,'('' Message will be permanent.'')')
+	   ELSE
+	      WRITE (6,'('' Expiration date will be '',A,''.'')')
+     &		EXPDAT(:TRIM(EXPDAT))
+	   END IF
+	END IF
+
+	IER = 1
+
+	RETURN
+
+1030	FORMAT(' It is ',A,'. Specify when message expires.')
+1031	FORMAT(' It is ',A,'. Specify when message expires.',
+     &		' Default is permanent.')
+1032	FORMAT(' It is ',A,'. Specify when message expires.',
+     &		' Default is ',I3,' days.')
+1035    Format(' Enter absolute time: [dd-mmm-yyyy] hh:mm:ss ',
+     &		'or delta time: dddd hh:mm:ss')
+1040	FORMAT(' ERROR: Invalid date format specified.')
+1045	FORMAT(' ERROR: Specified time has already passed.')
+1050	FORMAT(' ERROR: Specified expiration period too large.'
+     &		' Limit is ',I3,' days.')
+
+	END
+
+
+	SUBROUTINE MAILEDIT(INFILE,OUTFILE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER*(*) INFILE,OUTFILE
+
+	CHARACTER*80 MAIL_EDIT,OUT
+	DATA MAIL_EDIT /' '/
+
+	CHARACTER*132 INPUT
+
+	CHARACTER*256 SPAWN_COMMAND
+
+	EXTERNAL ERROR_TRAP
+
+	IF (CAPTIVE(2)) THEN
+	   WRITE (6,'('' ERROR: /EDIT not allowed from CAPTIVE account.'')')
+	   RETURN
+	END IF
+
+	IF (MAIL_EDIT.EQ.' ') THEN
+	  IF (.NOT.SYS_TRNLNM('MAIL$EDIT',MAIL_EDIT)) THEN
+	    OPEN (UNIT=10,FILE='VMSMAIL_PROFILE',
+     &	     DEFAULTFILE='SYS$SYSTEM:VMSMAIL_PROFILE.DATA',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+	    IF (IER.EQ.0) THEN
+	      DO WHILE (REC_LOCK(IER))
+	         READ(10,'(A)',KEY=USERNAME,IOSTAT=IER) INPUT
+	      END DO
+	      CLOSE (UNIT=10)
+	      IF (IER.EQ.0) THEN
+		 INPUT = INPUT(32:)
+		 DO WHILE (TRIM(INPUT).GT.0)
+		    IF (ICHAR(INPUT(1:1)).EQ.8) THEN
+		       MAIL_EDIT = 'CALLABLE_'//INPUT(5:4+ICHAR(INPUT(3:3)))
+		       INPUT = ' '
+		    ELSE
+		       INPUT = INPUT(ICHAR(INPUT(3:3))+5:)
+	            END IF
+	         END DO
+	      END IF
+	    END IF
+	  END IF
+	  CALL STR$UPCASE(MAIL_EDIT,MAIL_EDIT)
+	END IF
+
+	OUT = OUTFILE
+	IF (TRIM(OUT).EQ.0) THEN
+	   OUT = INFILE
+	END IF
+
+	CALL DISABLE_PRIVS
+	CALL DECLARE_CTRLC_AST
+	IF (TRIM(MAIL_EDIT).GT.0
+     &		.AND.INDEX(MAIL_EDIT,'CALLABLE_').EQ.0) THEN
+	   IF (MAIL_EDIT(:1).EQ.'@') MAIL_EDIT = MAIL_EDIT(2:)
+	   IF (OUT.EQ.INFILE) THEN
+	      SPAWN_COMMAND = '$@'//MAIL_EDIT(:TRIM(MAIL_EDIT))
+     &		//' "" '//OUT(:TRIM(OUT))
+	   ELSE
+	      SPAWN_COMMAND = '$@'//MAIL_EDIT(:TRIM(MAIL_EDIT))
+     &		//' '//INFILE//' '//OUT(:TRIM(OUT))
+	   END IF
+	   CALL LIB$SPAWN(SPAWN_COMMAND)
+	ELSE
+	   IF (TRIM(MAIL_EDIT).EQ.0) MAIL_EDIT = 'CALLABLE_EDT'
+
+C           The string CALLABLE_ was found.  Extract the editor name from the
+C           string and look up the entry point in the shareable image.
+
+	   N = INDEX(MAIL_EDIT,'_')+1
+	   IER = LIB$FIND_IMAGE_SYMBOL(
+     &		MAIL_EDIT(N:TRIM(MAIL_EDIT))//'SHR',
+     &		MAIL_EDIT(N:TRIM(MAIL_EDIT))//'$EDIT',ENTRYADDR)
+	   IF (IER) THEN
+	      CONTEXT = 0
+	      IER1 = LIB$FIND_FILE(INFILE,INPUT,CONTEXT)
+	      IF (MAIL_EDIT.EQ.'CALLABLE_EDT') THEN
+	         IF (.NOT.IER1) THEN
+	            CALL EDT$EDIT('NL:',OUT)
+	         ELSE
+	            CALL EDT$EDIT(INFILE,OUT)
+	         END IF
+	      ELSE
+                 IF (.NOT.IER1) THEN
+                    CALL EDITMESSAGE(%VAL(ENTRYADDR),' ',OUT)
+                 ELSE
+                    CALL EDITMESSAGE(%VAL(ENTRYADDR),INFILE,OUT)
+                 END IF
+	      END IF
+	      CALL LIB$ESTABLISH(ERROR_TRAP)
+	      IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+              CALL LIB$REVERT
+	   ELSE
+	      WRITE(6,'('' Could not activate editor.'')')
+	   END IF
+        END IF
+	CALL CANCEL_CTRLC_AST
+	CALL ENABLE_PRIVS
+
+	RETURN
+	END
+
+
+
+        SUBROUTINE EDITMESSAGE(EDITOR,INFILE,OUTFILE)
+
+        CHARACTER*(*) INFILE,OUTFILE
+
+        EXTERNAL EDITOR
+
+        CALL EDITOR(INFILE,OUTFILE)
+
+        RETURN
+        END
+
+
+
+	SUBROUTINE CREATE_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRCDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /REALPROC/ REALPROCPRIV(2)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	LOGICAL*1 QUOTA(32)
+
+	DIMENSION IMAGEPRIV(2)
+
+	CHARACTER IMAGENAME*132,ANSWER*4
+
+	IF (.NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: You do not have the privileges '',
+     &			''to execute the command.'')')
+	   CALL EXIT
+	END IF
+
+	JUST_STOP = CLI$PRESENT('STOP')
+
+	IF (JUST_STOP.AND..NOT.BTEST(REALPROCPRIV(1),PRV$V_SETPRV)) THEN
+	   WRITE (6,'('' ERROR: You need SETPRV to execute /STOP.'')')
+	   CALL EXIT
+	ELSE IF (.NOT.JUST_STOP.AND.
+     &			.NOT.BTEST(REALPROCPRIV(1),PRV$V_SYSNAM)) THEN
+	   CALL SYS$SETPRV(,,,IMAGEPRIV)
+	   IF (.NOT.BTEST(IMAGEPRIV(1),PRV$V_SYSNAM)) THEN
+	      WRITE (6,'('' ERROR: This new version of BULLETIN'',
+     &			'' needs to be installed with SYSNAM.'')')
+	      CALL EXIT
+	   END IF
+	END IF
+
+	IF (TEST_BULLCP()) THEN
+	   IF (.NOT.JUST_STOP) THEN
+	      WRITE (6,'('' BULLCP process running.
+     & Do you wish to kill it and restart a new one? '',$)')
+	      READ (5,'(A)') ANSWER(:1)
+	      IF (ANSWER(:1).NE.'Y'.AND.ANSWER(:1).NE.'y') CALL EXIT
+	   END IF
+
+	   CALL DELPRC('BULLCP',IER)
+
+	   IF (.NOT.IER) THEN
+	      CALL SYS_GETMSG(IER)
+	      CALL EXIT
+	   ELSE IF (JUST_STOP) THEN
+	      WRITE (6,'('' BULLCP process has been terminated.'')')
+	      CALL EXIT
+	   END IF
+	ELSE IF (JUST_STOP) THEN
+	   WRITE (6,'('' BULLCP is not presently running.'')')
+	   CALL EXIT
+	END IF
+
+	CALL GETIMAGE(IMAGENAME,ILEN)
+
+	LEN_B = TRIM(FOLDER_DIRECTORY)
+
+	CALL SYS$SETDFPROT('AA00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD:RW,GROUP:RW)
+C
+C  Generate a new BULLCP.COM each time.  This is done in case the BULLETIN
+C  executeable is moved, or a new version of BULLETIN is being installed that
+C  has changes to BULLCP.COM.  (It's also a security risk to execute the old
+C  copy, as someone might have been able to write into that directory and
+C  replace BULLCP.COM, and the command procedure is executed under the
+C  SYSTEM account, so it has all privileges.)
+C
+	OPEN(UNIT=11,FILE=FOLDER_DIRECTORY(:LEN_B)//'BULLCP.COM',
+     &		STATUS='NEW',IOSTAT=IER,CARRIAGECONTROL='LIST')
+	IF (IER.NE.0) RETURN
+	WRITE(11,'(A)') '$SET NOON'
+	WRITE(11,'(A)') '$B:=$'//IMAGENAME(:ILEN)
+	WRITE(11,'(A)') '$LOOP:'
+	WRITE(11,'(A)') '$PURGE '//FOLDER_DIRECTORY(:LEN_B)//'BULLCP.LOG'
+	WRITE(11,'(A)') '$DEF/USER SYS$OUTPUT '
+     &				//FOLDER_DIRECTORY(:LEN_B)//'BULLCP.LOG'
+	WRITE(11,'(A)') '$DEF/USER SYS$ERROR '
+     &				//FOLDER_DIRECTORY(:LEN_B)//'BULLCP.ERR'
+	WRITE(11,'(A)') '$B/BULLCP'
+	WRITE(11,'(A)') '$WAIT 00:01:00'
+	WRITE(11,'(A)') '$GOTO LOOP'		! File open timed out
+	CLOSE(UNIT=11)
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	CALL GETQUOTA(QUOTA,1)
+
+	IER = 0
+	DO WHILE (IER.EQ.0.OR.IER.EQ.SS$_DUPLNAM)
+	   IER = SYS$CREPRC(,'SYS$SYSTEM:LOGINOUT',FOLDER_DIRECTORY(:LEN_B)
+     &		//'BULLCP.COM','NL:',,,QUOTA,'BULLCP',%VAL(4),
+     &		,,%VAL(PRC$M_NOUAF+PRC$M_DETACH))
+	END DO
+
+	IF (IER) THEN
+	   OPEN(UNIT=11,FILE=FOLDER_DIRECTORY(:LEN_B)//'BULLCP.COM;-1',
+     &		STATUS='OLD',IOSTAT=IER1)
+	   IF (IER1.EQ.0) CLOSE(UNIT=11,STATUS='DELETE',IOSTAT=IER1)
+	END IF
+
+	IF (.NOT.IER) THEN
+	   CALL SYS_GETMSG(IER)
+	ELSE
+	   IF (CONFIRM_USER('DECNET').NE.0) THEN
+	      WRITE (6,'('' WARNING: Account with username DECNET'',
+     &				'' does not exist.'')')
+	      WRITE (6,'('' BULLCP will be owned by present account.'')')
+	   END IF
+	   WRITE (6,'('' Successfully created BULLCP detached process.'')')
+	END IF
+	CALL EXIT
+
+	END
+
+
+
+
+
+
+	SUBROUTINE FIND_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /BCP/ BULLCP
+	DATA BULLCP /0/
+
+	CHARACTER*80 TEMP
+
+	IER = SYS_TRNLNM('BULL_BULLCP',TEMP)
+	IF (IER.AND.TEMP.NE.'IGNORE') BULLCP = 1
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION TEST_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /BCP/ BULLCP
+	LOGICAL BULLCP
+
+	TEST_BULLCP = BULLCP
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE RUN_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BCP/ BULLCP
+	LOGICAL BULLCP
+
+	COMMON /KNOWN_FOLDERS/ FOLDER_Q1,NUM_FOLDERS
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /BBOARD_LOOP/ BBOARD_LOOP
+
+	CHARACTER*24 OLD_TIME,NEW_TIME
+
+        COMMON /MAIN_FOLDER_DIRECTORY/ FOLDER1_DIRECTORY
+	CHARACTER*80 FOLDER1_DIRECTORY
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	IF (TEST_BULLCP()) CALL EXIT	! BULLCP already running, so exit.
+
+	CALL LIB$DATE_TIME(OLD_TIME)
+
+	BULLCP = 2			! Enable process to do BULLCP functions
+
+	IER = SYS$CREMBX(%VAL(1),CHAN,,,,,'BULL_BULLCP')
+	IF (.NOT.IER) THEN		! Can't create mailbox, so exit.
+	   CALL SYS_GETMSG(IER)
+	   CALL EXIT
+	END IF
+
+	IER = SYS$DELMBX(%VAL(CHAN))	! If process dies, mailbox is deleted.
+
+	CALL REGISTER_BULLCP
+
+	CALL SET_REMOTE_SYSTEM
+
+	CALL START_DECNET
+
+	BBOARD_LOOP = 0
+	NEWS_LOOP = 0
+	NOW = SYS_TRNLNM('BULL_NEWS_CLEANUP','DEFINED')
+
+	DO WHILE (NEWS_LOOP.GE.0)		! Loop once every 15 minutes
+	   CALL SYS$SETAST(%VAL(0))
+
+	   UPDATEBBOARD = 1
+	   IF (SYS_TRNLNM('BULL_BBOARD_UPDATE',BULL_PARAMETER)) THEN
+	      LEN_P = TRIM(BULL_PARAMETER)
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER,IOSTAT=IER)
+     &		  UPDATEBBOARD
+	      IF (IER.EQ.0) UPDATEBBOARD = (UPDATEBBOARD+14) / 15
+	   END IF
+
+	   UPDATENEWS = 4
+	   IF (SYS_TRNLNM('BULL_NEWS_UPDATE',BULL_PARAMETER)) THEN
+	      LEN_P = TRIM(BULL_PARAMETER)
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER,IOSTAT=IER)
+     &		  UPDATENEWS
+	      IF (IER.EQ.0) UPDATENEWS = (UPDATENEWS+14) / 15
+	   END IF
+
+	   CALL LIB$DATE_TIME(NEW_TIME)
+	   CALL GET_PROXY_ACCOUNTS	! Proxy info for incoming connections
+	   FOLDER1_DIRECTORY = FOLDER_DIRECTORY
+	   CALL SYS$SETAST(%VAL(1))
+
+           IF (.NOT.NOW) NOW = INDEX(NEW_TIME,' 03:').NE.0.AND.
+     &                     INDEX(OLD_TIME,' 03:').EQ.0
+	   IER = 1
+	   DO WHILE (IER)
+	      CALL BBOARD			! Look for BBOARD messages.
+	      FOLDER_Q = FOLDER_Q1		! Init queue pointer to header
+	      POINT_FOLDER = 0
+	      DO WHILE (POINT_FOLDER.LT.NUM_FOLDERS)
+		 POINT_FOLDER = POINT_FOLDER + 1
+		 CALL SYS$SETAST(%VAL(0))
+		 CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+		 IF (FOLDER_BBOARD(:2).NE.'::') THEN
+		    CALL SELECT_FOLDER(.FALSE.,IER)	! Select folder
+		    IF (IER) THEN
+		       CALL DELETE_EXPIRED	! Delete expired messages
+		       IF (NOW) THEN	! Do empty block cleanup at 3 a.m.
+			  IF (NEMPTY.GT.200) THEN
+			     CALL CLEANUP_BULLFILE	! Cleanup empty blocks
+			  END IF
+		       END IF
+		    END IF
+		 END IF
+	         IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+		    CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	         END IF
+		 CALL SYS$SETAST(%VAL(1))
+	      END DO
+	      IF (NOW) THEN  ! Cleanup deleted users from files at 3 a.m.
+	         CALL SYS$SETAST(%VAL(0))
+	         CALL TOTAL_CLEANUP_LOGIN
+	         CALL SYS$SETAST(%VAL(1))
+	      END IF
+	      CALL SYS$SETAST(%VAL(0))
+	      CALL REGISTER_BULLCP
+	      IER1 = 1
+	      DO WHILE (IER1)
+	         IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',
+     &			   FOLDER_DIRECTORY)
+	         IF (IER.AND.FOLDER_DIRECTORY.EQ.FOLDER1_DIRECTORY) THEN 
+		    IER1 = 1
+	         ELSE
+		    IER1 = 0
+		 END IF
+      	      END DO
+	      IF (IER) CALL ADD_DIRECTORIES
+	      CALL SYS$SETAST(%VAL(1))
+	   END DO
+
+           CALL SYS$SETAST(%VAL(0)) 
+	   FOLDER_DIRECTORY = FOLDER1_DIRECTORY
+           CALL ADD_DIRECTORIES
+           CALL SYS$SETAST(%VAL(1))
+
+	   BBOARD_LOOP = BBOARD_LOOP + 1
+	   IF (BBOARD_LOOP.EQ.UPDATEBBOARD) BBOARD_LOOP = 0
+
+	   CALL SYS$SETAST(%VAL(0))
+	   IF (SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED').AND.
+     &	      (NEWS_LOOP.EQ.0.OR.NOW)) THEN
+	      IF (NOW) THEN
+	         CALL CREATE_PROCESS('BULLCP NEWS1')
+	      ELSE
+	         CALL CREATE_PROCESS('BULLCP NEWS')
+	      END IF
+           END IF
+	   CALL SYS$SETAST(%VAL(1))
+
+	   C = 0
+	   IF (LIB$FIND_FILE(FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &			//'*.SMTP',INPUT,C)) THEN
+	      CALL CREATE_PROCESS('BULLCP SMTP')
+	   END IF
+
+	   NOW = .FALSE.
+
+	   NEWS_LOOP = NEWS_LOOP + 1
+	   IF (NEWS_LOOP.EQ.UPDATENEWS) NEWS_LOOP = 0
+
+	   OLD_TIME = NEW_TIME
+	   CALL HIBER('15')		! Wait for 15 minutes
+C
+C  Look at remote folders and update local info to reflect new messages.
+C  Do here after waiting in case problem with connecting to remote folder
+C  which requires killing process.
+C
+
+	   FOLDER_Q = FOLDER_Q1
+	   POINT_FOLDER = 0
+	   DO WHILE (POINT_FOLDER.LT.NUM_FOLDERS)
+	      POINT_FOLDER = POINT_FOLDER + 1
+	      CALL SYS$SETAST(%VAL(0))
+	      CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      IF (FOLDER_BBOARD(:2).EQ.'::') THEN
+		 CALL SELECT_FOLDER(.FALSE.,IER)
+	      END IF
+	      CALL SYS$SETAST(%VAL(1))
+	   END DO
+	   CALL SYS$SETAST(%VAL(0))
+	   FOLDER_NUMBER = 0			! Reset to GENERAL folder
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL SYS$SETAST(%VAL(1))
+	END DO
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE SET_REMOTE_SYSTEM
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	DIMENSION NEW_SYSTEM_FLAG(FLONG)
+
+	CALL LIB$SYS_TRNLOG('SYS$NODE',,NODENAME)
+	NODENAME = NODENAME(2:INDEX(NODENAME,':')-1)
+
+ 	CALL OPEN_BULLFOLDER_SHARED
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   CALL READ_FOLDER_FILE(IER)
+	   IF (BTEST(FOLDER_FLAG,2))
+     &		CALL SET2(NEW_SYSTEM_FLAG,FOLDER_NUMBER)
+	   IF (FOLDER_BBOARD(:2).EQ.'::'.AND.BTEST(FOLDER_FLAG,2)
+     &		.AND.IER.EQ.0) THEN
+	      CALL CLOSE_BULLFOLDER
+	      CALL SETUSER(FOLDER_OWNER)
+	      CALL SELECT_FOLDER(.FALSE.,IER1)
+	      IF (IER1) THEN
+	         WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER1) 14,
+     &			BTEST(FOLDER_FLAG,2),NODENAME
+	      END IF
+	      CALL SETUSER(USERNAME)
+ 	      CALL OPEN_BULLFOLDER_SHARED
+	      CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFOLDER
+
+	FOLDER_NUMBER = 0			! Reset to GENERAL folder
+	CALL SELECT_FOLDER(.FALSE.,IER)
+
+	FOLDER1_FLAG = FOLDER_FLAG
+	DO FOLDER_NUMBER=0,FOLDER_MAX-1
+	   IF (TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND..NOT.
+     &	       TEST2(NEW_SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,2)
+	      CALL MODIFY_SYSTEM_LIST(0)
+	   END IF
+	END DO
+	FOLDER_FLAG = FOLDER1_FLAG
+	FOLDER_NUMBER = 0
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE REGISTER_BULLCP
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INTEGER SHUTDOWN_BTIM(FLONG)
+
+	EQUIVALENCE (SHUTDOWN_BTIM,BRIEF_FLAG)
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER REGNODE*8
+
+	CALL OPEN_BULLUSER
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*SYSTEM',IOSTAT=IER) 
+     &		TEMP_USER,REGNODE,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END DO
+
+	CALL LIB$SYS_TRNLOG('SYS$NODE',,NODENAME)
+	NODENAME = NODENAME(2:INDEX(NODENAME,':')-1)
+
+	IF (IER.NE.0) THEN
+	   DO I=1,FLONG
+	      SYSTEM_FLAG(I) = 0
+	      SHUTDOWN_FLAG(I) = 0
+	   END DO
+	   CALL SET2(SYSTEM_FLAG,0)
+	   NODE_AREA = 0
+	   WRITE (4,IOSTAT=IER)
+     &		'*SYSTEM     ',NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	   CALL CLOSE_BULLUSER
+	ELSE
+	   DO I=1,FLONG
+	      SHUTDOWN_FLAG(I) = SYSTEM_FLAG(I)
+	   END DO
+	   REWRITE (4,IOSTAT=IER)
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+           IF (NODENAME.EQ.REGNODE) THEN
+	      CALL CLOSE_BULLUSER
+	      RETURN
+	   END IF
+	   TEMP_USER = ':'
+	   DO WHILE (TEMP_USER(:1).EQ.':')
+	      DO WHILE (REC_LOCK(IER))		 
+	         READ (4,KEYGT=TEMP_USER,IOSTAT=IER)
+     &		   TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+		 TEMP_USER = TEMP_USER(:TRIM(TEMP_USER))
+	      END DO
+	      IF (TEMP_USER(:1).NE.':'.OR.IER.NE.0) THEN
+		 CALL CLOSE_BULLUSER
+		 RETURN
+	      END IF
+	      OPEN (UNIT=REMOTE_UNIT,STATUS='UNKNOWN',IOSTAT=IER,RECL=256,
+     &		FILE=TEMP_USER(2:LEN(TEMP_USER))//'::"TASK=BULLETIN1"')
+
+	      IF (IER.NE.0) THEN
+		 CALL ERRSNS(IDUMMY,IDUMMY,INODE)
+	         IF (INODE.EQ.%LOC(SS$_NOSUCHNODE).OR.
+     &		     INODE.EQ.%LOC(SS$_NOSUCHOBJ).OR.INODE.EQ.0) THEN
+		    DELETE (4)
+		 END IF
+	      ELSE
+		 WRITE (REMOTE_UNIT,'(3A)',IOSTAT=IER)
+     &			16,REGNODE,NODENAME
+	      END IF
+	      CLOSE (UNIT=REMOTE_UNIT)
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE UPDATE_SHUTDOWN(FOLDER_NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INTEGER SHUTDOWN_BTIM(FLONG)
+
+	EQUIVALENCE (SHUTDOWN_BTIM,BRIEF_FLAG)
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
+	CHARACTER NODENAME*8
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	CALL OPEN_BULLUSER
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*SYSTEM',IOSTAT=IER) 
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END DO
+
+	CALL CLR2(SHUTDOWN_FLAG,FOLDER_NUMBER)
+
+	SEEN_FLAG = 0
+	DO I=1,FLONG
+	   IF (SHUTDOWN_FLAG(I).NE.0) SEEN_FLAG = 1
+	END DO
+	IF (SEEN_FLAG.EQ.0) NODE_AREA = 0	! All done with that node
+
+	IF (IER.NE.0) THEN
+	   WRITE (4,IOSTAT=IER)
+     &		'*SYSTEM     ',NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	ELSE
+	   REWRITE (4,IOSTAT=IER)
+     &		TEMP_USER,NODENAME,NODE_NUMBER,NODE_AREA,NEW_FLAG,
+     &		SYSTEM_FLAG,SHUTDOWN_BTIM,SHUTDOWN_FLAG
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE HIBER(MIN)
+C
+C SUBROUTINE HIBER
+C
+C FUNCTION: Waits for specified time period in minutes.
+C
+	IMPLICIT INTEGER (A-Z)
+	INTEGER TIMADR(2)			! Buffer containing time
+						! in desired system format.
+	CHARACTER MIN*(*)
+
+	IER=SYS$BINTIM('0 00:'//MIN//':00.00',TIMADR)
+	IER=SYS$SCHDWK(,,TIMADR,)		! Set timer.
+	IER=SYS$HIBER()
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE WAIT_SEC(PARAM)
+C
+C SUBROUTINE WAIT_SEC
+C
+C FUNCTION: Waits for specified time period in seconds.
+C
+	IMPLICIT INTEGER (A-Z)
+	INTEGER TIMADR(2)			! Buffer containing time
+						! in desired system format.
+	CHARACTER PARAM*(*)
+	DATA WAIT_EF /0/
+
+	IF (WAIT_EF.EQ.0) CALL LIB$GET_EF(WAIT_EF)
+
+	IER=SYS$BINTIM('0 00:00:'//PARAM//'.00',TIMADR)
+	IER=SYS$SETIMR(%VAL(WAIT_EF),TIMADR,,%VAL(3))	! Set timer.
+	IER=SYS$WAITFR(%VAL(WAIT_EF))		! Wait for EFN to be set.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELETE_EXPIRED_NEWS(NOW)
+C
+C  SUBROUTINE DELETE_EXPIRED_NEWS
+C
+C  FUNCTION:
+C
+C  Delete any expired message in local news folders.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+ 	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+        COMMON /BULLFIL/ BULLFIL
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+
+	COMMON /NEWSLIST/ NEWSLIST
+
+	COMMON /DIRLIST/ DIRLIST
+
+	CHARACTER*4 GET_VMS_VERSION
+
+	INTEGER TODAY(2),NEXT_EX_BTIM(2),NO_EXPIRE(2)
+
+	CHARACTER*8 TODAY_KEY,TEMP
+	CHARACTER ASCTIME*24
+
+	IF (.NOT.SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) RETURN
+
+	IF (NOW) THEN 
+       	   IER = SYS$SETPRN('BULL NEWS1')
+	   IF (.NOT.IER) CALL EXIT
+	   IER = SYS$SETPRN('BULL NEWS')
+	   IF (.NOT.IER) CALL EXIT
+	END IF
+
+	FOLDER_NUMBER = 1000
+
+	FOLDER_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY)-1)//'.]'
+
+	CALL OPEN_BULLNEWS_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1)
+	END DO
+
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLNEWS
+	   RETURN
+	END IF
+
+	CALL SYS_BINTIM('-',TODAY)
+	
+	CALL GET_MSGKEY(TODAY,TODAY_KEY)
+
+	REMOTE_SET = 4
+	
+C
+C	A bug keeps messing up the last expired date key so that stored
+C	news groups do not get found.  Someday when this is fixed, we can
+C	add code like this:
+C
+C	INPUT = GET_VMS_VERSION()
+C	IF (INPUT(:2).EQ.'V5'.OR.INPUT(:2).EQ.'V4') VMSOLD = .TRUE..AND.NOW
+
+	DO WHILE (IER.EQ.0)
+	   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NEXT_EX_BTIM)
+
+	   DO WHILE (REC_LOCK(IER).OR.(NOW.AND.IER.EQ.0.AND.
+     &		(.NOT.BTEST(NEWS_F_FLAG,8).OR.
+     &		 COMPARE_BTIM(TODAY,NEWEST_EXBTIM).LT.0)))
+	      IF (NOW) THEN
+	         READ (7,IOSTAT=IER) NEWS_FOLDER_COM
+	         CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),
+     &				 %DESCR(NEWEST_EXBTIM))
+	      ELSE
+	         READ (7,IOSTAT=IER,KEYLE=TODAY_KEY,KEYID=3) NEWS_FOLDER_COM
+	      END IF
+	   END DO
+	   CALL NEWS_TO_FOLDER
+
+	   UNLOCK 7
+
+	   IF (IER.NE.0) THEN
+	      CALL CLOSE_BULLNEWS
+	      GO TO 1000
+           END IF
+
+	   IF (.NOT.BTEST(FOLDER_FLAG,8)) GO TO 900
+
+	   CALL OPEN_BULLDIR_SHARED
+
+	   CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),%DESCR(NEWEST_EXBTIM))
+
+	   DEL_COUNT = 0
+	   NDEL = -1
+	   DS = .FALSE.
+	   DN = .FALSE.
+	   CALL READ_FIRST_EXPIRED(NDEL)
+	   DO WHILE (NDEL.GT.0)
+	      DIFF = COMPARE_BTIM(TODAY,EX_BTIM)
+	      IF (DIFF.GT.0) THEN
+	         IF (NDEL.EQ.F_START) DS = .TRUE.
+	         IF (NDEL.EQ.F_NBULL) DN = .TRUE.	
+                 IF (NDEL.GT.NEWS_F_END) THEN
+	            CALL READ_NEXT_EXPIRED(NDEL)
+		 ELSE IF (COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).GE.0) THEN
+      		    DEL_COUNT = DEL_COUNT + 1
+	            CALL READ_NEXT_EXPIRED(NDEL)
+	         ELSE IF (EXDATE(8:11).LT.'1995') THEN	! Deleted manually?
+	            IF (LENGTH.GT.0) CALL DUMP_MESSAGE()
+		    CALL SYS$ASCTIM(,ASCTIME,TODAY,)
+	            EXDATE = ASCTIME(:11) 
+		    EXTIME = ASCTIME(13:23)
+		    LENGTH = 0
+	      	    CALL WRITEDIR(MSG_NUM,IER)
+		    DEL_COUNT = 0
+	            CALL READ_FIRST_EXPIRED(NDEL)
+		 ELSE
+                    CALL READ_NEXT_EXPIRED(NDEL) 
+	         END IF
+	      ELSE
+		 CALL COPY2(NEXT_EX_BTIM,EX_BTIM)
+	         IF (F_COUNT.LE.DEL_COUNT.OR.NDEL.GT.NEWS_F_END) THEN
+		   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NEXT_EX_BTIM)
+		 END IF
+		 NDEL = 0
+                 UNLOCK 2
+ 	      END IF
+	   END DO
+	   CALL READ_FOLDER_FILE_KEYNAME(NEWS_FOLDER,IER)
+	   NEXT = .FALSE.
+	   CALL READDIR(F_START,IER)
+	   IF (DS.OR.F_START.EQ.IER) THEN
+	      IER = 0
+	      NEXT = .TRUE.
+              I = F_START
+              DO WHILE (F_NBULL.GE.I.AND.IER.EQ.0)
+		 I = I + 1
+		 IF (I.LE.F_NBULL) CALL READDIR(I,IER)
+		 IF (COMPARE_BTIM(EX_BTIM,NEXT_EX_BTIM).LT.0) IER = 0
+	      END DO
+              F_START = I
+	      NEXT = .FALSE.
+	   END IF
+	   CALL READDIR(F_NBULL,IER)
+	   IF (F_START.LT.F_NBULL.AND.(DN.OR.F_NBULL.EQ.IER)) THEN
+	      I = F_NBULL
+	      IER = I
+	      DO WHILE (I.GE.F_START.AND.IER.EQ.I)
+		 I = I - 1
+		 IF (I.GE.F_START) CALL READDIR(I,IER)
+		 IF (COMPARE_BTIM(EX_BTIM,NEXT_EX_BTIM).LT.0) IER = I
+	      END DO
+	      IF (I.GE.F_START) CALL COPY2(F_NEWEST_BTIM,MSG_BTIM)
+	      IF (I.NE.IER) F_NBULL = I
+	   END IF
+	   F_COUNT = MAX(0,F_COUNT - DEL_COUNT)
+	   CALL GET_MSGKEY(TODAY,NEWS_F_EXPIRED_DATE)
+	   FOLDER_FLAG = IBSET(FOLDER_FLAG,13)
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) THEN
+    	      CALL READ_FIRST_EXPIRED(NDEL)
+	      DO WHILE (NDEL.GT.0.AND.NDEL.LE.NEWS_F_END.AND.
+     &		COMPARE_BTIM(EX_BTIM,NEXT_EX_BTIM).LT.0)
+	         IF (LENGTH.GT.0) CALL DUMP_MESSAGE()
+	         DELETE (UNIT=2)
+    	         CALL READ_FIRST_EXPIRED(NDEL)
+	      END DO
+	      CALL READ_FOLDER_FILE_KEYNAME(NEWS_FOLDER,IER)
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,13)
+	      CALL GET_MSGKEY(NEXT_EX_BTIM,NEWS_F_EXPIRED_DATE)
+	      CALL REWRITE_FOLDER_FILE(IER)
+	   END IF
+           CALL CLOSE_BULLDIR
+	END DO
+
+900     CALL CLOSE_BULLNEWS
+
+1000	IF (NOW.OR.IER.EQ.0) THEN
+	   BULLNEWSDIR_FILE = FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWSDIR.*]'//'*.'
+	   INPUT = GET_VMS_VERSION()
+	   CALL LIB$DAY_OF_WEEK(TODAY,DAY)
+	   IF (DAY.NE.7) THEN
+	      IER = SYS_TRNLNM('BULL_NEWS_CLEANUP','DEFINED')
+	      IF (IER) THEN
+		 DAY = 7
+	         CALL DELLNM('BULL_NEWS_CLEANUP')
+	      END IF
+	   END IF
+	   IF (INPUT(:2).NE.'V5'.AND.INPUT(:2).NE.'V4') THEN
+	      CONTEXT = 0
+	      DO WHILE (LIB$FIND_FILE(BULLNEWSDIR_FILE,INPUT,CONTEXT))
+	         IER = CONV$RECLAIM(INPUT(:TRIM(INPUT)))
+	      END DO 
+	   ELSE IF (DAY.EQ.7) THEN
+	      REMOTE_SET = 4
+	      DIRLIST = .TRUE.
+	      NEWSLIST = .TRUE.
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL READ_FOLDER_FILE_KEYNUM(1000,IER)
+	      CALL READ_FOLDER_FILE(IER)
+	      CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NO_EXPIRE)
+	      DO WHILE (IER.EQ.0)
+	         UNLOCK 7
+		 CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),
+     &				 %DESCR(NEWEST_EXBTIM))
+		 IF (BTEST(FOLDER_FLAG,8)) THEN
+		    CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+		    C = 0
+	            IF (LIB$FIND_FILE(BULLNEWSDIR_FILE
+     &			(:TRIM(BULLNEWSDIR_FILE))//';1',INPUT,C)) THEN
+                       IER = LIB$DELETE_FILE(
+     &			BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))//';2')
+		    ELSE
+		       IER = LIB$RENAME_FILE(
+     &			BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE)),'*.*;1')
+		    END IF
+		    CALL OPEN_BULLDIR_SHARED
+		    OPEN (UNIT=9,FILE=BULLNEWSDIR_FILE,SHARED,
+     &	             BUFFERCOUNT=127,
+     &		     INITIALSIZE=(NEWSDIR_RECORD_LENGTH*F_COUNT)/512,
+     &	             STATUS='NEW',FORM='UNFORMATTED',DISPOSE='DELETE',
+     &	             RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,IOSTAT=IER,
+     &	             ORGANIZATION='INDEXED',RECORDTYPE='FIXED',
+     &	             KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	             57:64:CHARACTER),ACCESS='KEYED')
+		    IF (IER.NE.0) THEN
+		       CALL CLOSE_BULLDIR
+		       CALL CLOSE_BULLNEWS
+		       RETURN
+		    END IF
+		    DO WHILE (IER.EQ.0)
+		       DO WHILE (REC_LOCK(IER))
+		          READ (2,IOSTAT=IER) NEWSDIR_ENTRY
+		       END DO
+		       IF (IER.EQ.0) THEN
+			  WRITE (9,IOSTAT=IER) NEWSDIR_ENTRY
+			  IF (IER.NE.0) THEN
+			     CALL CLOSE_BULLDIR
+			     CALL CLOSE_BULLNEWS
+		             RETURN
+			  ELSE
+	     		     CALL GET_MSGKEY(%REF(NEWS_EX_BTIM_KEY),
+     &					     %DESCR(EX_BTIM))
+			     IF (COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).LT.0)
+     &			        CALL COPY2(NEWEST_EXBTIM,EX_BTIM)
+		          END IF
+		       END IF
+		    END DO
+		    CLOSE (UNIT=9,DISPOSE='KEEP')
+		    CALL CLOSE_BULLDIR_DELETE
+		    CALL GET_MSGKEY(NEWEST_EXBTIM,TEMP)
+		    IF (TEMP.NE.NEWS_F_EXPIRED_DATE) THEN 
+		       CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+		       NEWS_F_EXPIRED_DATE = TEMP
+	               CALL REWRITE_FOLDER_FILE(IER)
+		       CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+		    END IF
+		    IER = LIB$RENAME_FILE(
+     &			BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE)),'*.*;1')
+		 ELSE
+		    IF (NO_EXPIRE(1).NE.NEWEST_EXBTIM(1).OR.
+     & 			NO_EXPIRE(2).NE.NEWEST_EXBTIM(2)) THEN
+		       CALL GET_MSGKEY(NO_EXPIRE,NEWS_F_EXPIRED_DATE)
+	               CALL REWRITE_FOLDER_FILE(IER)
+		       CALL OPEN_BULLDIR
+		       CALL CLOSE_BULLDIR_DELETE
+		    ELSE 
+		       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+		    END IF
+		    IER = 1
+		    DO WHILE (IER)
+                      IER = LIB$DELETE_FILE(
+     &			 BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))//';')
+	            END DO
+		 END IF
+	         CALL READ_FOLDER_FILE(IER)
+	      END DO
+	      CALL CLOSE_BULLNEWS
+	   END IF
+	   DIRLIST = .FALSE.
+	   NEWSLIST = .TRUE.
+	   CALL COPY2(EX_BTIM,TODAY)
+           BULLFIL = 0
+	   IER = .TRUE.
+	   DO WHILE (IER)
+	      IER = SYS_BINTIM('1 00:00',DAY)
+	      IER = LIB$ADDX(EX_BTIM,DAY,EX_BTIM)
+	      CALL SET_BULLFIL
+	      IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &			'.BULLFIL;')
+	      IER = INDEX(FOLDER_FILE,']1JAN').EQ.0
+	   END DO
+	   J = INDEX(FOLDER_FILE,']')
+	   DECODE(2,'(I2)',FOLDER_FILE(J-2:J-1),IOSTAT=IER) YEAR
+	   IF (IER.EQ.0) THEN 
+	      DO I=1,10
+	         YEAR = YEAR - 1
+	         IF (YEAR.EQ.-1) YEAR = 99
+	         ENCODE(2,'(I2)',FOLDER_FILE(J-2:J-1),IOSTAT=IER) YEAR
+                 IF (IER.EQ.0) IER = LIB$DELETE_FILE(FOLDER_FILE(:J)
+     &                  //'*.*;*')
+	      END DO
+	   END IF
+           IER = LIB$DELETE_FILE(NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))
+     &                  //'BULLNEWS*.DIR;*')
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELETE_EXPIRED
+C
+C  SUBROUTINE DELETE_EXPIRED
+C
+C  FUNCTION:
+C
+C  Delete any expired bulletins (normal or shutdown ones).
+C  (NOTE: If bulletin files don't exist, they get created now by
+C  OPEN_FILE_SHARED.  Also, if new format has been defined for files,
+C  they get converted now.  The directory file has had it's record size
+C  lengthened in the past to include more info, and the bulletin file 
+C  was lengthened from 80 to 81 characters to include byte which indicated
+C  start of bulletin message.  However, that scheme was removed and
+C  was replaced with a 128 byte record compressed format).
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	CALL OPEN_BULLDIR_SHARED	! Open directory file
+	CALL OPEN_BULLFIL_SHARED	! Open bulletin file
+	CALL CLOSE_BULLFIL
+	CALL READDIR(0,IER)		! Get directory header
+	IF (IER.EQ.1) THEN		! Is header present?
+	   IER = COMPARE_DATE(NEWEST_EXDATE,' ') ! Yes. Any expired bulls?
+	   IF (IER.GT.20*356) IER = -1	! Check if latest expiration date valid.
+	   IF (IER.EQ.0) IER = COMPARE_TIME(NEWEST_EXTIME,' ')
+	   IF (SHUTDOWN.GT.0.AND.NODE_AREA.GT.0.AND.
+     &		(FOLDER_NUMBER.EQ.0.OR.BTEST(FOLDER_FLAG,2)).AND.
+     &		TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+			! Do shutdown messages exist and need to be checked?
+	      SHUTDOWN = 0
+	      IER1 = -1
+	   ELSE
+	      IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+		 CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+	      END IF
+	      IER1 = 1
+	   END IF
+	   IF (IER.LE.0.OR.IER1.LE.0) THEN
+	      CALL CLOSE_BULLDIR
+	      CALL OPEN_BULLDIR		! Reopen without sharing
+	      CALL UPDATE 		! Need to update
+	   END IF
+	ELSE		! If header not there, then first time running BULLETIN
+	   IF (FOLDER_NUMBER.EQ.0) THEN
+	      CALL OPEN_BULLUSER	! Create user file to be able to set
+	      CALL CLOSE_BULLUSER	! defaults, privileges, etc.
+	   END IF
+           IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+              CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+           END IF
+	END IF
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE BBOARD
+C
+C  SUBROUTINE BBOARD
+C
+C  FUNCTION: Converts mail to BBOARD into non-system bulletins.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /KNOWN_FOLDERS/ FOLDER_Q1,NUM_FOLDERS
+	DATA FOLDER_Q1/0/
+
+	COMMON /BBOARD_LOOP/ BBOARD_LOOP
+
+	COMMON /MAIL_INFO/ USE_INFROM
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+
+	CHARACTER*12 INEXDATE
+	CHARACTER INDESCRIP*(INPUT_LENGTH),INFROM*(INPUT_LENGTH),INTO*76
+	CHARACTER ACCOUNT_SAVE*8,USERNAME_SAVE*12
+	CHARACTER F_BBOARD*64,BBOARD_NAME*64
+
+	DIMENSION NEW_MAIL(FOLDER_MAX)
+
+	DATA SPAWN_EF/0/
+
+	CALL SYS$SETAST(%VAL(0))
+
+	IF (SPAWN_EF.EQ.0) CALL LIB$GET_EF(SPAWN_EF)
+
+	CALL DISABLE_CTRL
+
+	CALL INIT_QUEUE(FOLDER_Q1,FOLDER_COM)
+
+	FOLDER_Q = FOLDER_Q1
+
+	CALL OPEN_BULLFOLDER_SHARED		! Get folder file
+
+	NUM_FOLDERS = 0
+	IER = 0
+	DO WHILE (IER.EQ.0)			! Copy all bulletins from file
+	   CALL READ_FOLDER_FILE(IER)
+	   IF (IER.EQ.0) THEN
+	      NUM_FOLDERS = NUM_FOLDERS + 1
+	      CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   END IF
+	END DO
+
+	CALL CLOSE_BULLFOLDER			! We don't need file anymore
+	CALL SYS$SETAST(%VAL(1))
+
+	IF (TEST_BULLCP().EQ.2.AND.BBOARD_LOOP.NE.0) GO TO 900
+
+	CALL SYS$SETAST(%VAL(0))
+	CALL CHECK_MAIL(NEW_MAIL)
+	CALL SYS$SETAST(%VAL(1))
+
+	FOLDER_Q = FOLDER_Q1			! Init queue pointer to header
+
+	NBBOARD_FOLDERS = 0
+
+	POINT_FOLDER = 0
+
+1	POINT_FOLDER = POINT_FOLDER + 1
+	IF (POINT_FOLDER.GT.NUM_FOLDERS) GO TO 900
+
+	CALL SYS$SETAST(%VAL(0))
+
+	FOLDER_Q_SAVE = FOLDER_Q
+
+	CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+
+	IF (FOLDER_BBOARD(:4).EQ.'NONE'.OR.
+     &		FOLDER_BBOARD(:2).EQ.'::') GO TO 1
+
+	NBBOARD_FOLDERS = NBBOARD_FOLDERS + 1
+
+	IF (.NOT.NEW_MAIL(POINT_FOLDER)) GO TO 1
+C
+C  The process is set to the BBOARD uic and username in order to create
+C  a spawned process that is able to read the BBOARD mail (a real kludge).
+C
+
+	CALL GETUSER(USERNAME_SAVE)		! Get present username
+	CALL GETACC(ACCOUNT_SAVE)		! Get present account
+	CALL GETUIC(GROUP_SAVE,USER_SAVE)	! Get present uic
+
+	IF (TRIM(FOLDER_BBOARD).GT.0) THEN	! BBOARD name present?
+	   IER = SETUSER(FOLDER_BBOARD,USERNAME_SAVE)! Set to BBOARD username
+	   IF (IER.EQ.2) GO TO 910	! Can't set username. New VMS version?
+	   CALL SETACC(ACCOUNTB)	! Set to BBOARD account
+	   CALL SETUIC(IBCLR(GROUPB,31),IBCLR(USERB,31)) ! Set to BBOARD uic
+	END IF
+
+	LEN_B = TRIM(BBOARD_DIRECTORY)
+	IER = LIB$DELETE_FILE(BBOARD_DIRECTORY(:LEN_B)//
+     &		FOLDER_BBOARD(:TRIM(FOLDER_BBOARD))//'.TXT;*')
+				! Delete old TXT files left due to errors
+
+	IF (.NOT.BTEST(USERB,31).AND.(USERB.NE.0.OR.GROUPB.NE.0)) THEN
+	      						! If normal BBOARD user
+	   IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)
+     &		  //'READ_BOARD.COM','NL:','NL:',1,,,STATUS,SPAWN_EF)
+	   CALL SYS$SETAST(%VAL(1))
+	   IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	   CALL SYS$SETAST(%VAL(0))
+	   IF (((STATUS.AND.'1FFFF'X).EQ.RMS$_FNF) .OR.
+     &	    ((STATUS .AND. '1FFF0'X).EQ. (RMS$_SPL .AND. '1FFF0'X))) THEN
+	      CALL SYS$SETDFPROT('AA00'X,CUR_DEF_PROT)
+	      	! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD:RW,GROUP:RW)
+	      OPEN(UNIT=11,FILE=BBOARD_DIRECTORY(:LEN_B)//'READ_BOARD.COM',
+     &		   STATUS='NEW',ERR=910,CARRIAGECONTROL='LIST')
+	      WRITE(11,'(A)') '$ SET PROTECT=(W:RWED)/DEFAULT'
+	      WRITE(11,'(A)') '$ SET PROC/PRIV=SYSPRV'
+	      WRITE(11,'(A)')
+     &	       '$ DEFINE/USER EXTRACT_FILE '//BBOARD_DIRECTORY(:LEN_B)//
+     &	       '''F$GETJPI("","USERNAME")'''
+	      WRITE(11,'(A)') '$ MAIL'
+	      WRITE(11,'(A)') 'SELECT MAIL'
+	      WRITE(11,'(A)') 'READ'
+	      WRITE(11,'(A)') 'EXTRACT/ALL/APPEND EXTRACT_FILE'
+	      WRITE(11,'(A)') 'DELETE/ALL'
+	      WRITE(11,'(A)') 'READ/NEW'
+	      WRITE(11,'(A)') 'EXTRACT/ALL/APPEND EXTRACT_FILE'
+	      WRITE(11,'(A)') 'DELETE/ALL'
+	      WRITE(11,'(A)') 'SELECT/NEW'
+	      CLOSE(UNIT=11)
+	      CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+	      IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)
+     &		   //'READ_BOARD.COM','NL:','NL:',1,,,STATUS,SPAWN_EF)
+	      CALL SYS$SETAST(%VAL(1))
+	      IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	      CALL SYS$SETAST(%VAL(0))
+	   END IF
+	ELSE
+	   CONTEXT = 0
+	   IER = LIB$FIND_FILE(BBOARD_DIRECTORY(:LEN_B)//FOLDER_BBOARD
+     &	      (:TRIM(FOLDER_BBOARD))//'.COM',INPUT,CONTEXT)
+	   IF (IER) THEN
+	      IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)//
+     &		  FOLDER_BBOARD(:TRIM(FOLDER_BBOARD))//'.COM','NL:',
+     &		  'NL:',1,,,STATUS,SPAWN_EF)
+	      CALL SYS$SETAST(%VAL(1))
+	      IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	      CALL SYS$SETAST(%VAL(0))
+	   END IF
+	   IF (.NOT.IER.OR.((STATUS.AND.'1FFFF'X).EQ.RMS$_FNF) .OR.
+     &	    ((STATUS .AND. '1FFF0'X).EQ. (RMS$_SPL .AND. '1FFF0'X))) THEN
+	      IER = LIB$SPAWN('$@'//BBOARD_DIRECTORY(:LEN_B)//
+     &		'BOARD_SPECIAL.COM','NL:','NL:',1,,,STATUS,SPAWN_EF)
+	      CALL SYS$SETAST(%VAL(1))
+	      IF (IER) CALL SYS$WAITFR(%VAL(SPAWN_EF))
+	      CALL SYS$SETAST(%VAL(0))
+	   END IF
+	END IF
+
+	CALL READ_QUEUE(%VAL(FOLDER_Q_SAVE),FOLDER_Q,FOLDER_COM)
+
+	NBULL = F_NBULL
+
+	CALL SETACC(ACCOUNT_SAVE)		! Reset to original account
+	CALL SETUSER(USERNAME_SAVE)		! Reset to original username
+	CALL SETUIC(GROUP_SAVE,USER_SAVE)	! Reset to original uic
+
+	OPEN (UNIT=14,FILE=BBOARD_DIRECTORY(:LEN_B)//FOLDER_BBOARD
+     &	   (:TRIM(FOLDER_BBOARD))//'.TXT',STATUS='OLD',ERR=100)
+	READ (14,'(Q,A)',END=100) LEN_INPUT,INPUT ! Read first line
+	CALL SYS$SETAST(%VAL(1))
+
+5	CALL SYS$SETAST(%VAL(0))
+
+	CALL READ_QUEUE(%VAL(FOLDER_Q_SAVE),IDUMMY,FOLDER_COM)
+
+	DO WHILE (LEN_INPUT.GT.0)
+	   IF (INPUT(:5).EQ.'From:') THEN
+	      INFROM = INPUT(7:)		! Store username
+	   ELSE IF (INPUT(:5).EQ.'Subj:') THEN
+	      INDESCRIP = INPUT(7:)		! Store subject
+	   ELSE IF (INPUT(:3).EQ.'To:') THEN
+	      INTO = INPUT(5:)			! Store address
+	   END IF
+	   READ (14,'(Q,A)',END=100) LEN_INPUT,INPUT ! Read next line from mail
+	END DO
+
+	INTO = INTO(:TRIM(INTO))
+	CALL STR$TRIM(INTO,INTO)
+	CALL STR$UPCASE(INTO,INTO)
+	FLEN = TRIM(FOLDER_BBOARD)
+
+	IER = 0
+	CALL STRIP_HEADER(' ',-1,STRIP)
+	STRIP = .TRUE.
+	DO WHILE (IER.EQ.0.AND.STRIP)
+	   READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   IF (IER.EQ.0) THEN
+	      CALL STRIP_HEADER(INPUT,LEN_INPUT,STRIP)
+	      IF (STRIP.AND.INPUT(:5).EQ.'From:') INFROM = ' '
+	   END IF
+	END DO
+
+C
+C  If more than one folder has same BBOARD account, don't use the 
+C  To: line to determine which folder to put the mail message in.
+C
+	POINT_FOLDER1 = 0
+	FOLDER_Q2 = FOLDER_Q1
+	DUP = .FALSE.
+	DO WHILE (.NOT.DUP.AND.POINT_FOLDER1.LT.NUM_FOLDERS)
+	   CALL READ_QUEUE(%VAL(FOLDER_Q2),FOLDER_Q2,FOLDER1_COM)
+	   POINT_FOLDER1 = POINT_FOLDER1 + 1
+	   DUP = FOLDER.NE.FOLDER1.AND.FOLDER_BBOARD.EQ.FOLDER1_BBOARD
+	END DO
+	IF (DUP.OR..NOT.DETECT_BBOARD(INTO,FOLDER_BBOARD(:FLEN))) THEN
+	   FOUND = .FALSE.
+	   J = 0
+	   IF (DUP) J = 1
+	   DO WHILE (J.LT.2.AND..NOT.FOUND)
+	      J = J + 1
+	      POINT_FOLDER1 = 0
+	      FOLDER_Q2 = FOLDER_Q1
+	      FOUND = .FALSE.
+	      DO WHILE (.NOT.FOUND.AND.POINT_FOLDER1.LT.NUM_FOLDERS)
+		 CALL READ_QUEUE(%VAL(FOLDER_Q2),FOLDER_Q2,FOLDER1_COM)
+		 POINT_FOLDER1 = POINT_FOLDER1 + 1
+		 IF (POINT_FOLDER1.LE.NUM_FOLDERS.AND.
+     &		     FOLDER1_BBOARD(:2).NE.'::'.AND.
+     &		     FOLDER1_BBOARD(:4).NE.'NONE') THEN
+		    IF (J.EQ.1) THEN
+		       F_BBOARD = FOLDER1_BBOARD
+		       FOUND = INTO.EQ.F_BBOARD
+		    ELSE
+		       F_BBOARD = BBOARD_NAME(FOLDER1_BBOARD,FOLDER1_DESCRIP)
+		       FOUND = DETECT_BBOARD(INTO,F_BBOARD(:FLEN))
+		    END IF
+		    FLEN = TRIM(F_BBOARD)
+		    IF (.NOT.FOUND.AND.NHEAD.GT.1) THEN
+		       HEADER_Q = HEADER_Q1
+		       I = 1
+		       DO WHILE (I.LT.NHEAD.AND..NOT.FOUND)
+			  CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+			  FOUND = DETECT_BBOARD(INPUT,F_BBOARD(:FLEN))
+			  I = I + 1
+		       END DO
+		    END IF
+		 END IF
+	      END DO
+	   END DO
+	   IF (FOUND) FOLDER_COM = FOLDER1_COM
+	END IF
+
+	NUMHEAD = 0
+	IF (NHEAD.GT.0) NUMHEAD = NHEAD + 1
+
+	IF (NUMHEAD.GT.0) THEN
+	   HEADER_Q = HEADER_Q1
+	   CALL READ_QUEUE(%VAL(HEADER_Q),HEADER_Q,INPUT)
+	   LEN_INPUT = TRIM(INPUT)
+	   NUMHEAD = NUMHEAD - 1
+	END IF
+
+	DO WHILE (LEN_INPUT.EQ.1.AND.INPUT(:1).EQ.CHAR(12).AND.IER.EQ.0)
+	   READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   IF (INPUT(:5).EQ.'From:') GO TO 5
+	END DO		! If line is just form feed, the message is empty
+	IF (IER.NE.0) GO TO 100				! If end of file, exit
+
+	EFROM = 2
+	I = TRIM(INFROM)
+	DO WHILE (EFROM.GT.0.AND.I.GT.0)		! Strip off the date
+	   IF (INFROM(I:I).EQ.' ') EFROM = EFROM - 1	! From the "From:" line
+	   I = I - 1
+	END DO
+	IF (I.GT.0) INFROM = INFROM(:I)
+
+	FOLDER_NAME = FOLDER			! For broadcasts
+
+	SAVE_Q = HEADER_Q
+	SAVE_Q1 = HEADER_Q1
+	NHEAD1 = NHEAD
+	HEADER_Q1 = 0
+		! INIT_MESSAGE_ADD_BBOARD reinits header so save it
+	CALL INIT_MESSAGE_ADD_BBOARD(INFROM,INDESCRIP,IER)
+
+	ISTART = 0
+	NBLANK = 0
+	IER = 0
+	DO WHILE (IER.EQ.0)		! Move text to bulletin file
+	   IF (LEN_INPUT.EQ.0) THEN
+	      IF (ISTART.EQ.1) THEN
+		 NBLANK = NBLANK + 1
+	      END IF
+	   ELSE
+	      ISTART = 1
+	      DO I=1,NBLANK
+		 CALL WRITE_MESSAGE_LINE(' ')
+	      END DO
+	      NBLANK = 0
+	      CALL WRITE_MESSAGE_LINE(INPUT)
+	   END IF
+	   IF (NUMHEAD.EQ.0) THEN
+	      READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   ELSE IF (NUMHEAD.EQ.1) THEN
+	      INPUT = ' '
+	      LEN_INPUT = 1
+	      NUMHEAD = NUMHEAD - 1
+	   ELSE
+	      CALL READ_QUEUE(%VAL(SAVE_Q),SAVE_Q,INPUT)
+	      LEN_INPUT = TRIM(INPUT)
+	      NUMHEAD = NUMHEAD - 1
+	   END IF
+	   IF (LEN_INPUT.EQ.1.AND.INPUT(:1).EQ.CHAR(12)) THEN
+	      DO WHILE (LEN_INPUT.EQ.1.AND.INPUT(:1).EQ.CHAR(12)
+     &			.AND.IER.EQ.0)
+		 READ (14,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	      END DO
+	      IF (IER.EQ.0.AND.INPUT(:5).EQ.'From:') THEN
+		 IER = 1
+	      ELSE
+		 NBLANK = NBLANK + 1
+	      END IF
+	   END IF
+	END DO
+
+	USE_INFROM = .TRUE.
+
+	NHEAD = NHEAD1
+	HEADER_Q1 = SAVE_Q1
+
+	CALL FINISH_MESSAGE_ADD			! Totally finished with add
+
+	CALL SYS$SETAST(%VAL(1))
+
+	GO TO 5					! See if there is more mail
+
+100	CLOSE (UNIT=14,STATUS='DELETE')		! Close the input file
+	CALL SYS$SETAST(%VAL(1))
+	GO TO 1
+
+900	CALL SYS$SETAST(%VAL(0))
+
+	FOLDER_NUMBER = 0
+	CALL OPEN_BULLFOLDER_SHARED
+	CALL READ_FOLDER_FILE_KEYNUM(0,IER)
+	CALL CLOSE_BULLFOLDER
+	CALL ENABLE_CTRL
+	FOLDER_SET = .FALSE.
+
+	IF (NBBOARD_FOLDERS.EQ.0) THEN
+	   CALL OPEN_BULLUSER
+	   CALL READ_USER_FILE_HEADER(IER)
+	   CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',BBOARD_BTIM)
+	   REWRITE (4) USER_HEADER		! Rewrite header
+	   CALL CLOSE_BULLUSER
+	END IF
+	CALL SYS$SETAST(%VAL(1))
+
+	CALL SYS$SETAST(%VAL(0))
+	IF (SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) THEN
+	   CALL SYS$SETAST(%VAL(1))
+	   IF (.NOT.TEST_BULLCP().AND.TEST_BULLCP().NE.2)
+     &		CALL NEWS2BULL(.FALSE.)
+	END IF
+	CALL SYS$SETAST(%VAL(1))
+
+	RETURN
+
+910	WRITE (6,1010)
+	GO TO 100
+
+1010	FORMAT(' ERROR:Install program with CMKRNL privileges or relink.')
+
+	END
+
+
+
+
+	LOGICAL FUNCTION DETECT_BBOARD(INPUT,BBOARD)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,BBOARD
+
+	DETECT_BBOARD = .TRUE.
+
+	LEN_BBOARD = LEN(BBOARD) - 1
+	LEN_INPUT = TRIM(INPUT)
+
+	DO I=1,LEN_INPUT-LEN_BBOARD
+	   IF (.NOT.STREQ(INPUT(:4),'Subj').AND.
+     &		STREQ(INPUT(I:I+LEN_BBOARD),BBOARD).AND.
+     &		(I.EQ.1.OR..NOT.ALPHA(INPUT(I-1:I-1))).AND.
+     &		(I.EQ.LEN_INPUT-LEN_BBOARD.OR.
+     &		(INDEX('@%!',INPUT(I+LEN_BBOARD+1:I+LEN_BBOARD+1)).GT.0
+     &		.AND.(I.EQ.1.OR.(INPUT(I-1:I-1).NE.
+     &		INPUT(I+LEN_BBOARD+1:I+LEN_BBOARD+1).AND.
+     &		(INPUT(I-1:I-1).NE.'('.OR.
+     &		INPUT(I+LEN_BBOARD+1:I+LEN_BBOARD+1).NE.' ')))))) RETURN
+	END DO
+
+	DETECT_BBOARD = .FALSE.
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION ALPHA(IN)
+
+	CHARACTER*(*) IN
+
+	ALPHA = (ICHAR(IN).GE.ICHAR('A').AND.ICHAR(IN).LE.ICHAR('Z'))
+     &	    .OR.(ICHAR(IN).GE.ICHAR('a').AND.ICHAR(IN).LE.ICHAR('z'))
+
+	RETURN
+	END
+
+
+
+	CHARACTER*(*) FUNCTION BBOARD_NAME(FOLDER_BBOARD,FOLDER_DESCRIP)
+
+	CHARACTER*(*) FOLDER_BBOARD,FOLDER_DESCRIP
+
+	BBOARD_NAME = FOLDER_BBOARD
+
+	I = INDEX(FOLDER_DESCRIP,'<')
+	IF (I.EQ.0) RETURN
+
+	BBOARD_NAME = FOLDER_DESCRIP(I+1:)
+
+	I = INDEX(BBOARD_NAME,'%"')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(I+2:)
+
+	I = INDEX(BBOARD_NAME,'!')
+	DO WHILE (I.GT.0)
+	   BBOARD_NAME = BBOARD_NAME(I+1:)
+	   I = INDEX(BBOARD_NAME,'!')
+	END DO
+
+	I = INDEX(BBOARD_NAME,'>')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(:I-1)
+	I = INDEX(BBOARD_NAME,'@')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(:I-1)
+	I = INDEX(BBOARD_NAME,'%')
+	IF (I.GT.0) BBOARD_NAME = BBOARD_NAME(:I-1)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CREATE_PROCESS(COMMAND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRCDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	LOGICAL*1 QUOTA(32)
+
+	CHARACTER*132 IMAGENAME
+
+	CHARACTER*(*) COMMAND
+
+	CALL GETIMAGE(IMAGENAME,ILEN)
+
+	LEN_B = TRIM(BBOARD_DIRECTORY)
+
+	IER = 0
+	DO WHILE (IER.EQ.0)
+	   OPEN(UNIT=11,FILE=BBOARD_DIRECTORY(:LEN_B)//'BULL_COMMAND.COM',
+     &		STATUS='OLD',IOSTAT=IER)
+	   IF (IER.EQ.0) CLOSE(UNIT=11,STATUS='DELETE')
+	END DO
+
+	CALL SYS$SETDFPROT('AA00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD:RW,GROUP:RW)
+	OPEN(UNIT=11,FILE=BBOARD_DIRECTORY(:LEN_B)//'BULL_COMMAND.COM',
+     &		STATUS='NEW',IOSTAT=IER,CARRIAGECONTROL='LIST')
+	IF (IER.NE.0) RETURN
+	IF (INDEX(IMAGENAME,';').GT.0) ILEN = INDEX(IMAGENAME,';')
+	WRITE(11,'(A)') '$B:=$'//IMAGENAME(:ILEN)
+	WRITE(11,'(A)') '$ON ERROR THEN GOTO EXIT'
+	WRITE(11,'(A)') '$ON SEVERE THEN GOTO EXIT'
+	WRITE(11,'(A)') '$ON WARNING THEN GOTO EXIT'
+	WRITE(11,'(A)') '$B/'//'''F$PROCESS()'''
+	WRITE(11,'(A)') '$EXIT:'
+	WRITE(11,'(A)') '$LOGOUT'
+	CLOSE(UNIT=11)
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	DEL = .FALSE.
+	IER = .FALSE.
+
+	CALL GETQUOTA(QUOTA,0)
+
+	DO WHILE (.NOT.IER)
+	   IER = SYS$CREPRC(,'SYS$SYSTEM:LOGINOUT',
+     &	    BBOARD_DIRECTORY(:LEN_B)//'BULL_COMMAND.COM','NL:',,
+     &	    PROCPRIV,QUOTA,COMMAND(:TRIM(COMMAND))
+     &	    ,%VAL(4),,,%VAL(PRC$M_NOUAF+PRC$M_DETACH))
+	   IF (.NOT.IER.AND..NOT.DEL) THEN
+	      CALL DELPRC('BULLCP NEWS',DEL)
+	      IER = .NOT.DEL
+	   ELSE
+	      IER = .TRUE.
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GETQUOTA(QUOTA,CLI)
+C
+C  SUBROUTINE GETQUOTA
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PQLDEF)'
+
+	INCLUDE '($JPIDEF)'
+                              
+	LOGICAL*1 QUOTA(32)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,JPI$_DFWSCNT,%LOC(WSDEFAULT))
+	CALL ADD_2_ITMLST(4,JPI$_WSEXTENT,%LOC(WSEXTENT))
+	CALL ADD_2_ITMLST(4,JPI$_WSQUOTA,%LOC(WSQUOTA))
+	CALL ADD_2_ITMLST(4,JPI$_BYTLM,%LOC(BYTLM))
+	CALL ADD_2_ITMLST(4,JPI$_ENQLM,%LOC(ENQLM))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)	! Get Info command.
+
+	I = 1
+	IF (CLI) THEN
+	   IF (CLI$GET_VALUE('PGFLQUOTA',BULL_PARAMETER,LEN_P)) THEN 
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) PGFLQUOTA
+	      QUOTA(1) = PQL$_PGFLQUOTA
+	      CALL LIB$MOVC3(4,PGFLQUOTA,QUOTA((I-1)*5+2))
+	      I = I + 1
+	   END IF
+	   IF (CLI$GET_VALUE('WSEXTENT',BULL_PARAMETER,LEN_P)) THEN
+	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) WSEXTENT
+	   END IF
+	END IF
+ 	QUOTA((I-1)*5+1) = PQL$_WSEXTENT
+	CALL LIB$MOVC3(4,WSEXTENT,QUOTA((I-1)*5+2)) 
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_WSQUOTA
+	CALL LIB$MOVC3(4,WSQUOTA,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_WSDEFAULT
+	CALL LIB$MOVC3(4,WSDEFAULT,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_BYTLM
+	CALL LIB$MOVC3(4,BYTLM,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_ENQLM
+	CALL LIB$MOVC3(4,ENQLM,QUOTA((I-1)*5+2))
+	I = I + 1
+	QUOTA((I-1)*5+1) = PQL$_LISTEND
+	CALL LIB$MOVC3(4,0,QUOTA((I-1)*5+2))
+
+        RETURN
+	END
+	
+
+
+
+	SUBROUTINE GETUIC(GRP,MEM)
+C
+C  SUBROUTINE GETUIC(UIC)
+C
+C  FUNCTION:
+C	To get UIC of process submitting the job.
+C  OUTPUT:
+C	GRP   -    Group number of UIC
+C	MEM   -	   Member number of UIC
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,JPI$_GRP,%LOC(GRP))
+	CALL ADD_2_ITMLST(4,JPI$_MEM,%LOC(MEM))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)	! Get Info command.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_UPTIME(UPTIME_DATE,UPTIME_TIME)
+C
+C  SUBROUTINE GET_UPTIME
+C
+C  FUNCTION: Gets time of last reboot.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	INTEGER 	UPTIME(2)
+	CHARACTER*(*)	UPTIME_TIME,UPTIME_DATE
+	CHARACTER	ASCSINCE*24
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(8,SYI$_BOOTTIME,%LOC(UPTIME))
+	CALL END_ITMLST(GETSYI_ITMLST)
+
+	IER = SYS$GETSYI(,,,%VAL(GETSYI_ITMLST),,,)
+
+	CALL SYS$ASCTIM(,ASCSINCE,UPTIME,)
+
+	UPTIME_DATE = ASCSINCE(:11)
+	UPTIME_TIME = ASCSINCE(13:23)
+
+	RETURN	
+	END
+
+
+
+	CHARACTER*4 FUNCTION GET_VMS_VERSION
+C
+C  FUNCTION GET_VMS_VERSION
+C
+C  FUNCTION: Gets VMS version 
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($SYIDEF)'
+
+	CHARACTER VERSION*4
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(4,SYI$_NODE_SWVERS,%LOC(VERSION))
+	CALL END_ITMLST(GETSYI_ITMLST)
+
+	IER = SYS$GETSYI(,,,%VAL(GETSYI_ITMLST),,,)
+
+	GET_VMS_VERSION = VERSION
+
+	RETURN	
+	END
+
+
+
+	INTEGER FUNCTION GET_L_VAL(I)
+	INTEGER I
+	GET_L_VAL = I
+	RETURN
+	END
+
+
+
+	SUBROUTINE CHECK_MAIL(NEW_MAIL)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /KNOWN_FOLDERS/ FOLDER_Q1,NUM_FOLDERS
+	DATA FOLDER_Q1/0/
+
+	DIMENSION NEW_MAIL(1)
+
+	CHARACTER INPUT*132
+
+	INTEGER*2 COUNT
+
+	FOLDER_Q = FOLDER_Q1			! so reinit queue pointer
+
+	OPEN (UNIT=10,FILE='VMSMAIL_PROFILE',
+     &	     DEFAULTFILE='SYS$SYSTEM:VMSMAIL_PROFILE.DATA',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+
+	DO I=1,NUM_FOLDERS
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+
+	   IF (((.NOT.BTEST(USERB,31).AND.(USERB.NE.0.OR.GROUPB.NE.0)).OR.
+     &		 BTEST(GROUPB,31)).AND.FOLDER_BBOARD(:2).NE.'::'.AND.
+     &		 FOLDER_BBOARD(:4).NE.'NONE') THEN
+						! If normal BBOARD or /VMSMAIL
+	      DO WHILE (REC_LOCK(IER1))
+	         READ(10,'(A)',KEY=FOLDER_BBOARD,IOSTAT=IER1) INPUT
+	      END DO
+	      COUNT = 0
+	      IF (IER1.EQ.0) THEN
+		 INPUT = INPUT(32:)
+		 DO WHILE (TRIM(INPUT).GT.0)
+		    IF (ICHAR(INPUT(1:1)).EQ.1) THEN
+		       CALL LIB$MOVC3(2,%REF(INPUT(5:)),COUNT)
+		       INPUT = ' '
+		    ELSE
+		       INPUT = INPUT(ICHAR(INPUT(3:3))+5:)
+	            END IF
+	         END DO
+	      END IF
+	      IF (IER1.EQ.0.AND.(COUNT.GT.0.OR.IER.NE.0)) THEN
+		 NEW_MAIL(I) = .TRUE.
+	      ELSE
+		 NEW_MAIL(I) = .FALSE.
+	      END IF
+	   ELSE
+	      NEW_MAIL(I) = .TRUE.
+	   END IF
+	END DO
+
+	CLOSE (10)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETIMAGE(IMAGNAME,ILEN)
+C
+C  SUBROUTINE GETIMAGE(IMAGNAME,ILEN)
+C
+C  FUNCTION:
+C	To get image name of process.
+C  OUTPUT:
+C	IMAGNAME   -    Image name of process
+C	ILEN	   -	Length of imagename
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CHARACTER*(*) IMAGNAME
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST_WITH_RET(LEN(IMAGNAME),JPI$_IMAGNAME,
+     &					%LOC(IMAGNAME),%LOC(ILEN))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)	! Get Info command.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NEWEST_MSG(IN_BTIM,START)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	DIMENSION IN_BTIM(2)
+
+	IF (REMOTE_SET) THEN
+	   CALL REMOTE_GET_NEWEST_MSG(IN_BTIM,START)
+	ELSE
+	   CALL GET_MSGKEY(IN_BTIM,MSG_KEY)
+	   CALL READDIR_KEYGE(START)
+	   IF (START.EQ.0) THEN
+	      START = -1
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NOTIFY_REMOTE_USERS(IN_BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	DIMENSION IN_BTIM(2)
+
+	CALL GET_MSGKEY(IN_BTIM,MSG_KEY)
+	CALL READDIR_KEYGE(START)
+
+	IF (START.EQ.0) RETURN
+
+	CALL OPEN_BULLUSER_SHARED
+
+	IER = START + 1
+	DO WHILE (START+1.EQ.IER)
+	   IF (.NOT.BTEST(SYSTEM,3)) CALL NOTIFY_USERS(0)
+	   START = START + 1
+	   CALL READDIR(START,IER)
+	END DO
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE READ_NOTIFY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	CALL OPEN_BULLUSER_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*NOTIFY',IOSTAT=IER) TEMP_USER,NOTIFY_REMOTE
+	END DO
+
+	IF (IER.NE.0) THEN
+	   DO I=1,FLONG
+	      NOTIFY_REMOTE(I) = 0
+	   END DO
+	   WRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	END IF
+
+	CALL CLOSE_BULLDIR
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DELPRC(DELNAM,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CHARACTER*(*) DELNAM
+
+	DATA OBIO/0/,OCPU/0/,ODIO/0/
+
+	CHARACTER PRCNAM*16
+
+	TEST = 'BULLCP NEWS'.EQ.DELNAM
+
+	WILDCARD = -1
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	
+	CALL ADD_2_ITMLST(LEN(PRCNAM),JPI$_PRCNAM,%LOC(PRCNAM))
+	CALL ADD_2_ITMLST(4,JPI$_PID,%LOC(PID))
+	IF (TEST) THEN 
+           CALL ADD_2_ITMLST(4,JPI$_BUFIO,%LOC(BIO))
+           CALL ADD_2_ITMLST(4,JPI$_CPUTIM,%LOC(CPU))
+           CALL ADD_2_ITMLST(4,JPI$_DIRIO,%LOC(DIO))
+	END IF
+ 	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+	IER = SYS$GETJPIW(,,DELNAM(:LEN(DELNAM)),%VAL(GETJPI_ITMLST),,,,)
+	IF (.NOT.IER) THEN 
+	   IER = 1
+	   DO WHILE (IER.AND.PRCNAM(:LEN(DELNAM)).NE.DELNAM)
+						! Get next interactive process
+	      IER = SYS$GETJPIW(,WILDCARD,,%VAL(GETJPI_ITMLST),,,,)
+						! Get next process.
+	   END DO
+	END IF
+	IF (IER.AND.PID.NE.0) THEN 
+	   IF (TEST.AND.
+     &		(BIO.GT.OBIO.OR.DIO.GT.ODIO.OR.CPU.GT.OCPU+10)) THEN
+	      OBIO = BIO
+	      ODIO = DIO
+	      OCPU = CPU
+	      IER = 0
+	      RETURN
+	   END IF
+	   IER = SYS$DELPRC(PID,)
+	   IF (IER.AND.TEST) THEN
+              OBIO = 0
+              ODIO = 0
+              OCPU = 0  
+	   END IF
+	END IF
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin4.for b/decus/vmslt98a/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..30bf4b588bee6ae905b8a70fb377ab279334af51
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin4.for
@@ -0,0 +1,2346 @@
+C
+C  BULLETIN4.FOR, Version 12/17/97
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+C
+C  SUBROUTINE ITMLST_SUBS
+C
+C  FUNCTION:
+C	A set of routines to easily create item lists.  It allows one
+C  to easily create item lists without the need for declaring arrays
+C  or itemlist size.  Thus, the code can be easily changed to add or
+C  delete item list codes.
+C
+C  Here is an example of how to use the routines (prints file to a queue):
+C
+C	CALL INIT_ITMLST	! Initialize item list
+C				! Now add items to list
+C	CALL ADD_2_ITMLST(LEN,SJC$_FILE_SPECIFICATION,%LOC(FILENAME))
+C	CALL ADD_2_ITMLST(9,SJC$_QUEUE,%LOC(QUEUE))
+C	CALL END_ITMLST(SNDJBC_ITMLST)	! Get address of itemlist
+C	IER = SYS$SNDJBCW(,%VAL(SJC$_ENTER_FILE),,%VAL(SNDJBC_ITMLST),IOSB,,)
+C
+	SUBROUTINE ITMLST_SUBS
+
+	IMPLICIT INTEGER (A-Z)
+
+	DATA SAVE_ITMLST_ADDRESS/0/,NUM_ITEMS/0/,QUEUE_HEADER/0/
+
+	ENTRY INIT_ITMLST
+
+	IF (QUEUE_HEADER.EQ.0) THEN	! First time INIT_ITMLST ever called?
+	   CALL LIB$GET_VM(8,QUEUE_HEADER)  ! Yes, create queue header pointer
+	   CALL LIB$MOVC3(4,0,%VAL(QUEUE_HEADER))	! Zero out header
+	   CALL LIB$MOVC3(4,0,%VAL(QUEUE_HEADER+4))	! Zero out header
+	ELSE IF (SAVE_ITMLST_ADDRESS.GT.0) THEN	! Clean out old item list
+	   CALL LIB$FREE_VM((NUM_ITEMS+1)*12,SAVE_ITMLST_ADDRESS)
+	   NUM_ITEMS = 0		! Release old itemlist memory
+	   SAVE_ITMLST_ADDRESS = 0
+	ELSE				! ITMLST calls cannot be nested.
+	   WRITE (6,'('' ERROR: INIT_ITMLST called before previous'',$)')
+	   WRITE (6,'(''+ ITMLST terminated with END_ITMLST.'')')
+	   CALL EXIT
+	END IF
+
+	RETURN
+
+
+	ENTRY ADD_2_ITMLST(BUFLEN,CODE,BUFADR)
+C
+C  ITMLST entries are initially stored in a queue.  Each queue entry
+C  needs 8 bytes for pointer + 12 bytes for itemlist info.
+C
+	CALL LIB$GET_VM(20,INPUT_ITMLST)	! Get memory for entry
+
+	CALL STORE_ITMLST_ENTRY(%VAL(INPUT_ITMLST+8),BUFLEN,CODE,BUFADR,0)
+						! Store data in itemlist format
+	CALL LIB$INSQTI(%VAL(INPUT_ITMLST),%VAL(QUEUE_HEADER))
+						! Insert entry into queue
+	NUM_ITEMS = NUM_ITEMS + 1		! Increment item count
+
+	RETURN
+
+
+	ENTRY ADD_2_ITMLST_WITH_RET(BUFLEN,CODE,BUFADR,RETADR)
+C
+C  ITMLST entries are initially stored in a queue.  Each queue entry
+C  needs 8 bytes for pointer + 12 bytes for itemlist info.
+C
+	CALL LIB$GET_VM(20,INPUT_ITMLST)	! Get memory for entry
+
+	CALL STORE_ITMLST_ENTRY(%VAL(INPUT_ITMLST+8),BUFLEN,CODE,BUFADR,
+     &							RETADR)
+						! Store data in itemlist format
+	CALL LIB$INSQTI(%VAL(INPUT_ITMLST),%VAL(QUEUE_HEADER))
+						! Insert entry into queue
+	NUM_ITEMS = NUM_ITEMS + 1		! Increment item count
+
+	RETURN
+
+
+	ENTRY END_ITMLST(ITMLST_ADDRESS)
+
+	CALL LIB$GET_VM((NUM_ITEMS+1)*12,ITMLST_ADDRESS)
+						! Get memory for itemlist
+	SAVE_ITMLST_ADDRESS = ITMLST_ADDRESS	! Save address to remove memory
+
+	DO I=1,NUM_ITEMS			! Place entries into itemlist
+	   CALL LIB$REMQHI(%VAL(QUEUE_HEADER),INPUT_ITMLST)
+	   CALL LIB$MOVC3(12,%VAL(INPUT_ITMLST+8),
+     &		%VAL(ITMLST_ADDRESS+(I-1)*12))
+	   CALL LIB$FREE_VM(20,INPUT_ITMLST)
+	END DO
+
+	CALL LIB$MOVC3(4,0,%VAL(ITMLST_ADDRESS+NUM_ITEMS*12))
+					! Place terminating 0 at end of itemlist
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE STORE_ITMLST_ENTRY(INPUT_ITMLST,BUFLEN,CODE,BUFADR,
+     &							RETADR)
+
+	IMPLICIT INTEGER (A-Z)
+
+	STRUCTURE /ITMLST/
+	 UNION
+	  MAP
+	   INTEGER*2 BUFLEN,CODE
+	   INTEGER BUFADR,RETADR
+	  END MAP
+	 END UNION
+	END STRUCTURE
+
+	RECORD /ITMLST/ INPUT_ITMLST(1)
+
+	INPUT_ITMLST(1).BUFLEN = BUFLEN
+	INPUT_ITMLST(1).CODE = CODE
+	INPUT_ITMLST(1).BUFADR = BUFADR
+	INPUT_ITMLST(1).RETADR = RETADR
+
+	RETURN
+	END
+
+
+	SUBROUTINE CLEANUP_LOGIN
+C
+C  SUBROUTINE CLEANUP_LOGIN
+C
+C  FUNCTION: Removes entry in user file of user that no longer exist.
+C		It creates empty space for new user.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER*12 LOGIN_USER
+
+	CHARACTER TODAY*24
+
+	DIMENSION TODAY_BTIM(2)
+
+	MARK = SYS_TRNLNM_SYSTEM('BULL_MARK','DEFINED')
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	CALL OPEN_SYSUAF_SHARED
+
+	LOGIN_USER = USERNAME
+	READ (4,IOSTAT=IER1,KEYGT=USERNAME) USER_ENTRY	! Look forward one
+	TEMP_USER = USERNAME
+	USERNAME = LOGIN_USER
+	DO WHILE (REC_LOCK(IER))
+	   READ (8,KEY=TEMP_USER,IOSTAT=IER) TEMP_USER	! See if user exists
+	END DO
+
+	IF (IER.NE.0.AND.IER1.EQ.0.AND.TEMP_USER.NE.USER_HEADER_KEY) THEN
+				! If no UAF entry and last login was
+				! more than 6 months old, delete entry
+	   IF (MINUTE_DIFF(TODAY_BTIM,LOGIN_BTIM).GT.6*30*24*60) THEN
+	      DELETE(UNIT=4)			! Delete non-existant user
+	      CALL OPEN_BULLINF
+	      READ (9,KEY=TEMP_USER,IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE(UNIT=9)
+	      LU = TRIM(TEMP_USER)
+	      IF (MARK) CALL LIB$DELETE_FILE('BULL_MARK:'//
+     &					TEMP_USER(:LU)//'.*MARK;*')
+	      TEMP_USER(LU:LU) = CHAR(ICHAR(TEMP_USER(LU:LU)).OR.128)
+	      READ (9,KEY=TEMP_USER,IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE(UNIT=9)
+	      IF (LU.GT.1) THEN
+	         TEMP_USER(LU-1:LU-1) = 
+     &			CHAR(128.OR.ICHAR(TEMP_USER(LU-1:LU-1)))
+	      ELSE
+		 TEMP_USER(2:2) = CHAR(128.OR.ICHAR(TEMP_USER(2:2)))
+	      END IF
+	      READ (9,KEY=TEMP_USER,IOSTAT=IER)
+	      IF (IER.EQ.0) DELETE(UNIT=9)
+	      CALL CLOSE_BULLINF
+	   END IF
+	END IF
+
+	CALL CLOSE_SYSUAF			! All done...
+
+	RETURN
+	END
+
+
+	SUBROUTINE TOTAL_CLEANUP_LOGIN
+C
+C  SUBROUTINE TOTAL_CLEANUP_LOGIN
+C
+C  FUNCTION: Removes all entries in user file of usesr that no longer exist
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	CHARACTER TODAY*24
+
+	DIMENSION TODAY_BTIM(2)
+
+	CALL SYS$ASCTIM(,TODAY,,)		! Get the present time
+	CALL SYS_BINTIM(TODAY,TODAY_BTIM)
+
+	MARK = SYS_TRNLNM_SYSTEM('BULL_MARK','DEFINED')
+
+	CALL OPEN_SYSUAF_SHARED
+	CALL OPEN_BULLUSER
+	CALL OPEN_BULLINF
+
+	TEMP_USER = USERNAME
+
+	IER = 0
+
+	DO WHILE (IER.EQ.0)			! Clean out BULLUSER.DAT
+	   READ (4,IOSTAT=IER) USER_ENTRY
+	   IF (IER.EQ.0.AND.USERNAME(:1).NE.'*'.AND.
+     &	       USERNAME(:1).NE.':'.AND.
+     &	       USERNAME.NE.USER_HEADER_KEY) THEN	! See if user exists
+	      DO WHILE (REC_LOCK(IER))
+	         READ (8,KEY=USERNAME,IOSTAT=IER)
+	      END DO
+	      IF (IER.NE.0) THEN 	! If no UAF entry and last login was
+					! more than 6 months old, delete entry
+		 IF (MINUTE_DIFF(TODAY_BTIM,LOGIN_BTIM).GT.6*30*24*60) THEN
+	            DELETE (UNIT=4)
+		    READ (9,KEY=USERNAME,IOSTAT=IER)
+		    IF (IER.EQ.0) DELETE (UNIT=9)
+	            LU = TRIM(USERNAME)
+		    IF (MARK) CALL LIB$DELETE_FILE('BULL_MARK:'//
+     &					USERNAME(:LU)//'.*MARK;*')
+	            USERNAME(LU:LU) = CHAR(ICHAR(USERNAME(LU:LU)).OR.128)
+		    READ (9,KEY=USERNAME,IOSTAT=IER)
+		    IF (IER.EQ.0) DELETE (UNIT=9)
+		    IF (LU.GT.1) THEN
+		       USERNAME(LU-1:LU-1) = 
+     &			 CHAR(128.OR.ICHAR(USERNAME(LU-1:LU-1)))
+		    ELSE
+		       USERNAME(2:2) = CHAR(128.OR.ICHAR(USERNAME(2:2)))
+		    END IF
+		    READ (9,KEY=USERNAME,IOSTAT=IER)
+		    IF (IER.EQ.0) DELETE (UNIT=9)
+		 END IF
+		 IER = 0
+	      ELSE
+		 DO I=0,FOLDER_MAX-1
+		    IF (TEST2(NOTIFY_FLAG,I)) THEN
+		       CALL SET2(NOTIFY_REMOTE,I)
+		    END IF
+		 END DO
+	      END IF
+	   END IF
+	END DO
+
+	CALL CLOSE_SYSUAF			! All done...
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*NOTIFY',IOSTAT=IER) TEMP_USER
+	END DO
+
+	IF (IER.NE.0) THEN
+	   WRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	ELSE
+	   REWRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	END IF
+
+	READ (9,KEYGT='            ',IOSTAT=IER) USERNAME
+
+	DO WHILE (IER.EQ.0)			! Clean out BULLINF.DAT
+	   LU = TRIM(USERNAME)
+	   USERNAME(LU:LU) = CHAR(ICHAR(USERNAME(LU:LU)).AND.127)
+	   IF (LU.GT.1) THEN
+	      USERNAME(LU-1:LU-1) = 
+     &			 CHAR(127.AND.ICHAR(USERNAME(LU-1:LU-1)))
+	   ELSE
+	      USERNAME(2:2) = CHAR(127.AND.ICHAR(USERNAME(2:2)))
+	   END IF
+	   READ (4,KEYEQ=USERNAME,IOSTAT=IER)
+	   IF (IER.NE.0) DELETE (UNIT=9)
+	   READ (9,IOSTAT=IER) USERNAME
+	END DO
+
+	CALL CLOSE_BULLINF
+	CALL CLOSE_BULLUSER
+
+	USERNAME = TEMP_USER
+
+	RETURN
+	END
+
+
+	SUBROUTINE COPY_BULL(INLUN,IBLOCK,OBLOCK,IER)
+C
+C  SUBROUTINE COPY_BULL
+C
+C  FUNCTION: To copy data to the bulletin file.
+C
+C  INPUT:
+C	INLUN	-	Input logical unit number
+C	IBLOCK	-	Input block number in input file to start at
+C	OBLOCK	-	Output block number in output file to start at
+C
+C  OUTPUT:
+C	IER	-	If error in writing to bulletin, IER will be <> 0.
+C
+C  NOTES:  Input file is accessed using sequential access.  This is 
+C	to allow files which have variable records to be read.  The
+C       bulletin file is assumed to be opened on logical unit 1.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_RECORD_WRITTEN/ OCOUNT
+
+	INCLUDE 'BULLDIR.INC'
+
+	IF (REMOTE_SET) THEN
+	   CALL REMOTE_COPY_BULL(IER)
+	   IF (IER.NE.0) CALL ERROR_AND_EXIT
+	END IF
+
+	DO I=1,IBLOCK-1
+	   READ(INLUN,'(A)')
+	END DO
+
+	OCOUNT = OBLOCK
+	ICOUNT = IBLOCK
+
+	NBLANK = 0
+	LENGTH = 0
+	DO WHILE (LENGTH.GE.0)
+	   ILEN = 0
+	   DO WHILE (ILEN.EQ.0)
+	      READ(INLUN,'(Q,A)',END=100) ILEN,INPUT
+	      ILEN = MIN(ILEN,TRIM(INPUT),LINE_LENGTH)
+	      IF (ILEN.GT.1.AND.ICHAR(INPUT(ILEN:ILEN)).EQ.10) THEN
+		 INPUT(ILEN-1:ILEN-1) = CHAR(32)	! Remove imbedded
+		 INPUT(ILEN:ILEN) = CHAR(32)	! CR/LFs at end of file.
+		 ILEN = ILEN - 2
+	      END IF
+	      IF (ILEN.GT.0) THEN
+		 IF (ICOUNT.EQ.IBLOCK) THEN
+		    IF (INPUT(:6).EQ.'From: ') THEN
+		       INPUT(:4) = 'FROM'
+		    END IF
+		 END IF
+		 ICOUNT = ICOUNT + 1
+	      ELSE IF (ILEN.EQ.0.AND.ICOUNT.GT.IBLOCK) THEN
+		 NBLANK = NBLANK + 1
+	      END IF
+	   END DO
+	   IF (NBLANK.GT.0) THEN
+	      DO I=1,NBLANK
+	         CALL STORE_BULL(1,' ',OCOUNT)
+	      END DO
+	      LENGTH = LENGTH + NBLANK*2
+	      NBLANK = 0
+	   END IF
+	   CALL STORE_BULL(ILEN,INPUT,OCOUNT)
+	   LENGTH = LENGTH + ILEN + 1
+	END DO
+
+100	LENGTH = (LENGTH+127)/128
+	IF (LENGTH.EQ.0) THEN
+	   IER = 1
+	ELSE
+	   IER = 0
+	END IF
+
+	CALL FLUSH_BULL(OCOUNT)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_BULL(ILEN,INPUT,OCOUNT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /STORE_POINT/ POINT
+	DATA POINT/-1/
+
+	CHARACTER INPUT*(*),OUTPUT*255
+
+	IF (POINT.EQ.-1) THEN
+	   POINT = 0
+	   IF (BTEST(FOLDER_FLAG,12)) CALL STORE_BULL1(0,CHAR(0),OCOUNT)
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,12)) THEN
+	   CALL COMPRESS(INPUT(:ILEN),OUTPUT,OLEN)
+	   CALL STORE_BULL1(OLEN,OUTPUT,OCOUNT)
+	ELSE
+	   CALL STORE_BULL1(ILEN,INPUT,OCOUNT)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_BULL1(ILEN,INPUT,OCOUNT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER BRECLEN=128
+
+	CHARACTER INPUT*(*),OUTPUT*256
+
+	COMMON /STORE_POINT/ POINT
+
+	IF (ILEN+POINT+1.GT.BRECLEN) THEN
+	   IF (POINT.EQ.BRECLEN) THEN
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:POINT))
+	      OUTPUT = CHAR(ILEN)//INPUT
+	      POINT = ILEN + 1
+	   ELSE IF (POINT.EQ.BRECLEN-1) THEN
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:POINT)//CHAR(ILEN))
+	      OUTPUT = INPUT
+	      POINT = ILEN
+	   ELSE
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:POINT)//CHAR(ILEN)
+     &		//INPUT(:BRECLEN-1-POINT))
+	      OUTPUT = INPUT(BRECLEN-POINT:)
+	      POINT = ILEN - (BRECLEN-1-POINT)
+	   END IF
+	   OCOUNT = OCOUNT + 1
+	   DO WHILE (POINT.GE.BRECLEN)
+	      CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:BRECLEN))
+	      OCOUNT = OCOUNT + 1
+	      OUTPUT = OUTPUT(BRECLEN+1:)
+	      POINT = POINT - BRECLEN
+	   END DO
+	ELSE
+	   OUTPUT(POINT+1:) = CHAR(ILEN)//INPUT(:ILEN)
+	   POINT = POINT + ILEN + 1
+	END IF
+
+	RETURN
+
+	ENTRY FLUSH_BULL(OCOUNT)
+
+	IF (POINT.LT.BRECLEN) OUTPUT(POINT+1:POINT+1) = CHAR(0)
+	CALL WRITE_BULL_FILE(OCOUNT,OUTPUT(:BRECLEN))
+	POINT = -1
+
+	RETURN
+
+	END
+
+
+	SUBROUTINE WRITE_BULL_FILE(OCOUNT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) OUTPUT
+
+	IF (REMOTE_SET) THEN
+	   CALL REMOTE_WRITE_BULL_FILE(OUTPUT)
+	ELSE
+	   WRITE (1'OCOUNT) OUTPUT
+	END IF
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_BULL_LINE(SBLOCK,BLENGTH,BUFFER,ILEN)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(*) BUFFER
+
+	COMMON /HEADER/ HEADER
+	LOGICAL HEADER /.TRUE./
+
+	COMMON /DATE/ DATE_LINE
+	CHARACTER*(INPUT_LENGTH) DATE_LINE
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REF/ REFERENCES,LREF
+	CHARACTER*256 REFERENCES
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+
+	IF (ILEN.GT.LINE_LENGTH) THEN		! First read?
+	   CALL STRIP_HEADER(' ',-1,IER)
+	   STRIP = .NOT.HEADER
+	   IBLOCK = SBLOCK			! Initialize pointers.
+	   BULL_HEADER = .TRUE.
+	   SEEN_FROM = .FALSE.
+	   SEEN_SUBJ = .FALSE.
+	   READ_HEAD = .FALSE.
+	   CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+	   IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+	   MSG_SENT = .FALSE.
+	   FINDREF = .NOT.STRIP.AND.REMOTE_SET.EQ.4
+	ELSE					! Else set ILEN to zero
+	   ILEN = 0				! to request next line
+	END IF
+
+	IF (MSG_SENT) THEN
+	   BUFFER = ' '
+	   ILEN = 1
+	   MSG_SENT = .FALSE.
+	   RETURN
+	END IF
+
+	DO WHILE (ILEN.GE.0)
+	   DO WHILE (ILEN.EQ.0)			! Read until line created
+	      CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+	      IF (ILEN.LE.0) IBLOCK = IBLOCK + 1    ! Need to read new record.
+	      IF (IBLOCK.GE.SBLOCK+BLENGTH) THEN    ! No more records.
+	         IF (STRIP.AND..NOT.READ_HEAD.AND.NHEAD.GT.0) THEN
+		     IBLOCK = SBLOCK
+		     ILEN = LINE_LENGTH+1
+		     CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+		     IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+		     READS = 0
+		     IF (SEEN_FROM) READS = READS + 1
+		     IF (SEEN_SUBJ) READS = READS + 1
+		     IF (MSG_SENT) READS = READS + 1
+		     IF (READS.GT.0) THEN
+		        DO I=1,READS
+		           ILEN = 0
+		           DO WHILE (ILEN.EQ.0)
+			      CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+			      IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+			   END DO
+		        END DO
+		     END IF
+		     STRIP = .FALSE.
+		 ELSE
+		     RETURN
+		 END IF
+	      END IF
+	   END DO
+
+	   IF (STRIP.OR.FINDREF) THEN
+	      IF (BULL_HEADER) THEN
+		 IF (BUFFER(:5).EQ.'From:'.AND..NOT.SEEN_FROM) THEN
+	            SEEN_FROM = .TRUE.
+		    RETURN
+		 ELSE IF (BUFFER(:5).EQ.'Subj:'.AND..NOT.SEEN_SUBJ) THEN
+	            SEEN_SUBJ = .TRUE.
+		    RETURN
+		 ELSE IF (BUFFER(:13).EQ.'Message sent:') THEN
+		    MSG_SENT = .TRUE.
+		    RETURN
+		 ELSE
+		    BULL_HEADER = .FALSE.
+		    IF (REMOTE_SET.EQ.4) FOUNDREF = .FALSE. 
+		 END IF
+	      END IF
+              IF (REMOTE_SET.EQ.4.AND.ILEN.GT.12.AND.
+     &			(BUFFER(1:11).EQ.'References:'.OR.
+     &			 BUFFER(1:11).EQ.'Message-ID:')) THEN
+	         IF (.NOT.FOUNDREF) LREF = 0
+	         FOUNDREF = .TRUE.
+		 IF (LREF.EQ.0) THEN
+		    REFERENCES = BUFFER(13:ILEN)
+		 ELSE
+		    REFERENCES = REFERENCES(:LREF)//' '//
+     &				BUFFER(13:ILEN)
+		 END IF
+		 LREF = TRIM(REFERENCES)
+	      END IF
+	      IF (STRIP) THEN
+	         IF (DATE_LINE.NE.' ') DATE_LINE = ' '
+	         CALL STRIP_HEADER(BUFFER,ILEN,STRIP)
+	         IF (DATE_LINE.NE.' '.AND..NOT.MAIL_POST()) THEN
+		    BUFFER = DATE_LINE
+		    ILEN = TRIM(DATE_LINE)
+		    MSG_SENT = .TRUE.
+		    RETURN
+	         END IF
+	         IF (STRIP.OR.(.NOT.STRIP.AND.TRIM(BUFFER).EQ.0)) ILEN = 0
+		 IF (STRIP.AND.BUFFER(:5).EQ.'From:') READ_HEAD = .TRUE.
+	         IF (.NOT.STRIP.AND..NOT.READ_HEAD.AND.NHEAD.GT.0) THEN
+		     IBLOCK = SBLOCK
+		     ILEN = LINE_LENGTH+1
+		     CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+		     IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+		     READS = 0
+		     IF (SEEN_FROM) READS = READS + 1
+		     IF (SEEN_SUBJ) READS = READS + 1
+		     IF (MSG_SENT) READS = READS + 1
+		     IF (READS.GT.0) THEN
+		        DO I=1,READS
+		           ILEN = 0
+		           DO WHILE (ILEN.EQ.0)
+			      CALL GET_BULL(IBLOCK,BUFFER,ILEN)
+			      IF (ILEN.LE.0) IBLOCK = IBLOCK + 1
+			   END DO
+		        END DO
+		     END IF
+		 END IF
+	      ELSE
+	         IF (.NOT.HEADER) THEN
+		    CALL STRIP_HEADER(BUFFER,ILEN,STRIP)
+		    STRIP = .FALSE.
+	         END IF
+	         IF (TRIM(BUFFER).EQ.0) THEN
+		    FINDREF = .FALSE.
+	            IF (.NOT.FOUNDREF) LREF = 0 
+	         END IF
+	         RETURN
+	      END IF
+	   ELSE
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+
+	ENTRY TEST_MORE_RECORDS(SBLOCK,BLENGTH,IREC)
+
+	IREC = (SBLOCK+BLENGTH-1) - IBLOCK
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_BULL(IBLOCK,BUFFER,OLEN)
+C
+C  SUBROUTINE GET_BULL
+C
+C  FUNCTION:  Outputs line from folder file.
+C
+C  INPUT:
+C	IBLOCK	-	Input block number in input file to read from.
+C
+C  OUTPUT:
+C	BUFFER  -	Character string containing output line.
+C	OLEN	-	Length of character string.  If 0, signifies that
+C			new record needs to be read, -1 signifies error.
+C
+C  NOTE:  Since message file is stored as a fixed length (128) record file,
+C	  but message lines are variable, message lines may span one or
+C	  more record.  This routine takes a record and outputs as many
+C	  lines as it can from the record.  When no more lines can be
+C	  outputted, it returns OLEN=0 requesting the calling program to
+C	  increment the record counter.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /REMOTE_READ_MESSAGE/ SCRATCH_R1
+	DATA SCRATCH_R1 /0/
+
+	PARAMETER BRECLEN=128
+
+	CHARACTER BUFFER*(*),TEMP*(BRECLEN), LEFT*(INPUT_LENGTH)
+
+	DATA POINT /1/, LEFT_LEN /0/
+
+	IF (OLEN.GT.LINE_LENGTH) THEN		! First read?
+	   POINT = 1				! Initialize pointers.
+	   LEFT_LEN = 0
+	   DTYPE = 0
+	END IF
+
+	IF (POINT.EQ.1) THEN			! Need to read new line?
+10	   IF (INCMD(:4).EQ.'MOVE'.OR.INCMD(:4).EQ.'COPY') THEN
+	      DO WHILE (REC_LOCK(IER))		! Read from file
+	         READ (11'IBLOCK,IOSTAT=IER) TEMP
+	      END DO
+	   ELSE IF (REMOTE_SET) THEN		! Remote folder?
+	      IF (IBLOCK.EQ.BLOCK) SCRATCH_R = SCRATCH_R1	! Read lines
+	      CALL READ_QUEUE(%VAL(SCRATCH_R),SCRATCH_R,TEMP)	! from queue
+	      IER = 0
+	   ELSE					! Local folder
+	      DO WHILE (REC_LOCK(IER))		! Read from file
+	         READ (1'IBLOCK,IOSTAT=IER) TEMP
+	      END DO
+	   END IF
+	   IF (OLEN.GT.LINE_LENGTH.AND.IER.EQ.0
+     &		.AND.ICHAR(TEMP(:1)).EQ.0) THEN
+	      DTYPE = 1
+	      POINT = POINT + 1
+           END IF
+	ELSE IF (POINT.EQ.BRECLEN+1) THEN	! Read all of line
+	   OLEN = 0				! so indicate need to read
+	   POINT = 1				! new line to calling routine.
+	   RETURN
+	END IF
+
+	IF (IER.GT.0) THEN			! Error in reading file.
+	   OLEN = -1				! OLEN = -1 signifies error
+	   POINT = 1
+	   LEFT_LEN = 0
+	   RETURN
+	END IF
+
+	IF (LEFT_LEN.GT.0) THEN			! Part of line is left from
+	   OLEN = ICHAR(LEFT(:1))		! previous record read.
+	   IF (LEFT_LEN.LE.BRECLEN) THEN	! Rest of it is in next record.
+ 	      IF (DTYPE.EQ.0) THEN
+	         BUFFER = LEFT(2:OLEN-LEFT_LEN+1)//
+     &					TEMP(:LEFT_LEN) ! Output line.
+	      ELSE
+	         CALL UNCOMPRESS(LEFT(2:OLEN-LEFT_LEN+1)
+     &				 //TEMP(:LEFT_LEN),BUFFER,OLEN)
+ 	      END IF
+	      POINT = LEFT_LEN + 1		! Update pointers.
+	      LEFT_LEN = 0
+	   ELSE					! Rest of line is longer than
+	      LEFT(OLEN-LEFT_LEN+2:) = TEMP	! a record, so store record
+	      LEFT_LEN = LEFT_LEN - BRECLEN	! and request another read.
+	      OLEN = 0				! Request new record read.
+	   END IF
+	ELSE					! Else nothing left over.
+	   OLEN = ICHAR(TEMP(POINT:POINT))	! Get line length
+	   IF (OLEN.GT.BRECLEN-POINT) THEN	! If it extends to next record
+	      LEFT = TEMP(POINT:)		! Store it in leftover buffer
+	      LEFT_LEN = OLEN - (BRECLEN-POINT)	! Store leftover length
+	      OLEN = 0				! Request new record read
+	      POINT = 1				! Update record pointer.
+	   ELSE IF (OLEN.EQ.0) THEN		! Empty line signifies
+	      POINT = 1				! end of message.
+	   ELSE					! Else message line fully read
+	      ILEN = OLEN
+	      IF (DTYPE.EQ.0) THEN
+	         BUFFER = TEMP(POINT+1:POINT+ILEN)	! So output it
+	         OLEN = OLEN
+	      ELSE
+	         CALL UNCOMPRESS(TEMP(POINT+1:POINT+ILEN),BUFFER,OLEN)
+	      END IF
+	      POINT = POINT+ILEN+1		! and update pointer.
+	   END IF
+	END IF
+
+	RETURN
+
+	ENTRY TEST_MORE_LINES(OLEN)	! Test for more lines in record.
+					! Returns length of next line.
+	IF (POINT.EQ.BRECLEN+1) THEN		! If pointer greater than
+	   OLEN = 0				! record, no more lines.
+	ELSE					! Else there is another line.
+	   OLEN = ICHAR(TEMP(POINT:POINT))	! Output it's length.
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE DELETE_ENTRY(BULL_ENTRY)
+C
+C  SUBROUTINE DELETE_ENTRY
+C
+C  FUNCTION:
+C	To delete a directory entry.
+C
+C  INPUTS:
+C	BULL_ENTRY  -  Bulletin entry number to delete
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	IF (NBULL.GT.0) THEN
+	   CALL READDIR(0,IER)
+	   NBULL = -NBULL
+	   CALL WRITEDIR(0,IER)
+	END IF
+
+	CALL DUMP_MESSAGE()
+
+	CALL READDIR(BULL_ENTRY,IER)
+	DELETE(UNIT=2)
+
+	NEMPTY = NEMPTY + LENGTH
+
+	CALL WRITEDIR(0,IER)
+
+	RETURN
+	END
+
+
+	SUBROUTINE DUMP_MESSAGE()
+C
+C  SUBROUTINE DUMP_MESSAGE
+C
+C  FUNCTION:
+C	To delete a directory entry.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($ACLDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /ACL/ ACLENT
+	CHARACTER ACLENT*256
+
+	CHARACTER DUMP_FILE*80
+
+	IF (BTEST(FOLDER_FLAG,1)) THEN
+	   DUMP_FILE = FOLDER_FILE
+           IF (REMOTE_SET.EQ.4) THEN
+	      DUMP_FILE = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	      DO I=1,TRIM(DUMP_FILE)
+                 IF (DUMP_FILE(I:I).EQ.'.') DUMP_FILE(I:I) = '_'
+	      END DO	
+	      DUMP_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//
+     &				DUMP_FILE
+	   END IF
+	   OPEN(UNIT=3,FILE=DUMP_FILE(:TRIM(DUMP_FILE))//'.LOG',
+     &		IOSTAT=IER,STATUS='OLD',
+     &		RECL=LINE_LENGTH,CARRIAGECONTROL='LIST',ACCESS='APPEND')
+	   IF (IER.NE.0) THEN
+	      OPEN(UNIT=3,FILE=DUMP_FILE(:TRIM(DUMP_FILE))//'.LOG',
+     &		IOSTAT=IER,
+     &		RECL=LINE_LENGTH,STATUS='NEW',CARRIAGECONTROL='LIST')
+	      IF (IER.NE.0) RETURN
+
+	      IER = SYS$PARSE_ACL('(IDENTIFIER='//FOLDER_OWNER(
+     &		:TRIM(FOLDER_OWNER))//',ACCESS=R+W+E+D+C)',ACLENT,,)
+       	      IF (IER) THEN
+		 CALL INIT_ITMLST	! Initialize item list
+		 CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_ADDACLENT,
+     &			%LOC(ACLENT))
+		 CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+		 IER = SYS$CHANGE_ACL(,ACL$C_FILE,DUMP_FILE(:TRIM(
+     &		   DUMP_FILE))//'.LOG',%VAL(ACL_ITMLST),,,)
+              END IF
+	   ELSE
+	      WRITE (3,'(A)') CHAR(12)
+	   END IF
+
+	   CALL OPEN_BULLFIL
+
+	   ILEN = LINE_LENGTH + 1
+
+	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
+	      WRITE(3,1060) INPUT(7:ILEN),DATE//' '//TIME(:8)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	   ELSE
+	      WRITE(3,1060) FROM,DATE//' '//TIME(:8)
+	   END IF
+	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
+	      WRITE(3,1050) INPUT(7:MIN(ILEN,LINE_LENGTH-3))
+	   ELSE
+	      WRITE(3,1050) DESCRIP
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END IF
+
+	   DO WHILE (ILEN.GT.0)
+	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
+	      IF (ILEN.GT.0) WRITE (3,'(A)') INPUT(:ILEN)
+	   END DO
+
+	   CLOSE (UNIT=3)			! Bulletin copy completed
+
+	   CALL CLOSE_BULLFIL
+	END IF
+
+1050	FORMAT('Subject: ',A,/)
+1060	FORMAT(/,'From: ',A,' Date: ',A11)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_EXDATE(EXDATE,NDAYS)
+C
+C  SUBROUTINE GET_EXDATE
+C
+C  FUNCTION:  Computes expiration date giving number of days to expire.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*12 EXDATE
+
+	CHARACTER*3 MONTHS(12)
+	DIMENSION LENGTH(12)
+	DATA MONTHS/'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP',
+     &		    'OCT','NOV','DEC'/
+	DATA LENGTH/31,27,31,30,31,30,31,31,30,31,30,31/
+
+	CALL SYS$ASCTIM(,EXDATE,,)		! Get the present date
+
+	DECODE(2,'(I2)',EXDATE(:2)) DAY	! Get day
+	DECODE(4,'(I4)',EXDATE(8:11)) YEAR	! Get year
+
+	MONTH = 1
+	DO WHILE (MONTHS(MONTH).NE.EXDATE(4:6))	! Get month
+	   MONTH = MONTH + 1
+	END DO
+
+	IF (MOD(YEAR,4).EQ.0) THEN		! Correct February length
+	   LENGTH(2) = 28			! if we're in a leap year
+	ELSE
+	   LENGTH(2) = 27
+	END IF
+
+	NUM_DAYS = NDAYS	! Put number of days into buffer variable
+
+	DO WHILE (NUM_DAYS.GT.0)
+	   IF (NUM_DAYS+DAY.GT.LENGTH(MONTH)) THEN
+				! If expiration date exceeds end of month
+	      NUM_DAYS = NUM_DAYS - (LENGTH(MONTH) - DAY + 1)
+				! Decrement # of days by days left in month
+	      DAY = 1				! Reset day to first of month
+	      MONTH = MONTH + 1			! Increment month pointer
+	      IF (MONTH.EQ.13) THEN		! Moved into next year?
+		 MONTH = 1			! Reset month pointer
+		 YEAR = YEAR + 1		! Increment year pointer
+	         IF (MOD(YEAR,4).EQ.0) THEN	! Correct February length
+	            LENGTH(2) = 28		! if we're in a leap year
+	         ELSE
+	            LENGTH(2) = 27
+	         END IF
+	      END IF
+	   ELSE			! If expiration date is within the month
+	      DAY = DAY + NUM_DAYS		! Find expiration day
+	      NUM_DAYS = 0			! Force loop exit
+	   END IF
+	END DO
+
+	ENCODE(2,'(I2)',EXDATE(:2)) DAY	! Put day into new date
+	ENCODE(4,'(I4)',EXDATE(8:11)) YEAR	! Put year into new date
+	EXDATE(4:6) = MONTHS(MONTH)		! Put month into new date
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_LINE(INPUT,LEN_INPUT)
+C
+C  SUBROUTINE GET_LINE
+C
+C  FUNCTION:
+C	Gets line of input from terminal.
+C
+C  OUTPUTS:
+C	LEN_INPUT  -  Length of input line.  If = -1, CTRLC entered.
+C		      if = -2, CTRLZ entered.
+C
+C  NOTES:
+C	Also, on first call, set LEN_INPUT to 1+LENGTH OF INPUT CHARCTER
+C	for initializing the CTRLC AST.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	LOGICAL*1 DESCRIP(8),DTYPE,CLASS
+	INTEGER*2 LENGTH
+	CHARACTER*(*) INPUT
+	EQUIVALENCE (DESCRIP(1),LENGTH),(DESCRIP(3),DTYPE)
+	EQUIVALENCE (DESCRIP(4),CLASS),(DESCRIP(5),POINTER)
+
+        DATA LENGTH/0/,DTYPE/0/,CLASS/2/,POINTER/0/
+
+	EXTERNAL SMG$_EOF
+
+	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
+	LOGICAL DECNET_PROC
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	CHARACTER PROMPT*(*),NULLPROMPT*4
+	LOGICAL USE_PROMPT
+
+	USE_PROMPT = .FALSE.
+
+	GO TO 5
+
+	ENTRY GET_INPUT_PROMPT(INPUT,LEN_INPUT,PROMPT)
+
+	USE_PROMPT = .TRUE.
+
+5	LIMIT = LEN(INPUT)			! Get input line size limit
+	INPUT = ' '				! Clean out input buffer
+
+C
+C  Initialize CTRL-C AST with AST routine CTRLC_ROUTINE and
+C  AST parameter FLAG.  When CTRLC occurs, FLAG is set to 1
+C
+
+	CALL DECLARE_CTRLC_AST
+
+	LEN_INPUT = 0				! Nothing inputted yet
+
+C
+C  LIB$GET_INPUT is nice way of getting input from terminal,
+C  as it handles such thing as accidental wrap around to next line.
+C
+
+	IF (DECNET_PROC) THEN
+	   READ (5,'(Q,A)',IOSTAT=IER) LEN_INPUT,INPUT
+	   IF (IER.NE.0) LEN_INPUT = -2 
+	   RETURN
+	ELSE IF (USE_PROMPT) THEN
+	   IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		DESCRIP,PROMPT)		! Get line from terminal with prompt
+	ELSE
+	   IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		DESCRIP,NULLPROMPT(:1))	! Get line from terminal with no prompt
+	END IF
+
+	IF (.NOT.IER.AND.IER.NE.%LOC(SMG$_EOF)) CALL EXIT(IER)
+
+	CALL STR$TRIM(DESCRIP,DESCRIP,LEN_INPUT)
+
+	IF (FLAG.EQ.0) THEN			! If no CTRL-C has occurred
+	   CALL CANCEL_CTRLC_AST		! Cancel CTRL-C AST
+	   IF (IER.NE.%LOC(SMG$_EOF)) THEN	! End of input?
+	      LEN_INPUT = MIN(LIMIT,LENGTH)	! No. Get length of line
+	      DO I=0,LEN_INPUT-1		! Extract from descriptor
+	         CALL GET_VAL(INPUT(I+1:I+1),%VAL(POINTER+I))
+	      END DO
+	      CALL CONVERT_TABS(INPUT,LEN_INPUT)
+	      LEN_INPUT = MAX(LEN_INPUT,LENGTH)
+	   ELSE
+	      LEN_INPUT = -2			! If CTRL-Z, say so
+	   END IF
+	ELSE
+	   LEN_INPUT = -1			! If CTRL-C, say so
+	END IF
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_TABS(INPUT,LEN_INPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT
+
+	PARAMETER TAB = CHAR(9)
+
+	LIMIT = LEN(INPUT)
+
+	DO WHILE (INDEX(INPUT,TAB).GT.0.AND.LEN_INPUT.LT.LIMIT)
+	   TAB_POINT = INDEX(INPUT,TAB)	! Remove tabs
+	   MOVE = ((TAB_POINT-1)/8)*8 + 9
+	   ADD = MOVE - TAB_POINT
+	   IF (MOVE-1.LE.LIMIT) THEN
+	      INPUT(MOVE:) = INPUT(TAB_POINT+1:)
+	      DO I = TAB_POINT,MOVE-1
+	         INPUT(I:I) = ' '
+	      END DO
+	      LEN_INPUT = LEN_INPUT + ADD - 1
+	   ELSE
+	      DO I = TAB_POINT,LIMIT
+	         INPUT(I:I) = ' '
+	      END DO
+	      LEN_INPUT = LIMIT+1
+	   END IF
+	END DO
+
+        CALL FILTER (INPUT, LEN_INPUT)
+
+	RETURN
+	END
+
+
+	SUBROUTINE FILTER (INCHAR, LENGTH)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INCHAR
+
+	DO I = 1,LENGTH
+	   IF ((INCHAR(I:I).LT.' '.AND.
+     &      INCHAR(I:I).NE.CHAR(13).AND.INCHAR(I:I).NE.CHAR(10)))
+     &	    INCHAR(I:I) = '.'
+	END DO
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_VAL(OUTPUT,INPUT)	! Used to convert logical
+	CHARACTER*(*) OUTPUT			! byte to character value
+	LOGICAL*1 INPUT
+	OUTPUT = CHAR(INPUT)
+	RETURN
+	END
+
+	SUBROUTINE CTRLC_ROUTINE		! CTRL-C AST routine
+	IMPLICIT INTEGER (A-Z)			! If CTRL-C, come here
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /DEF_PROT/ ORIGINAL_DEF_PROT
+
+	IF (FLAG.EQ.2) THEN
+	   CALL LIB$PUT_OUTPUT('Bulletin aborting...')
+	   CALL SYS$CANEXH()
+	   CALL SYS$SETDFPROT(ORIGINAL_DEF_PROT,)
+	   CALL LIB$ENABLE_CTRL(CTRLY,)		! Enable CTRL-Y & -C
+	   CALL EXIT
+	END IF
+	FLAG = 1				! to set flag
+	RETURN
+	END
+
+
+
+	SUBROUTINE DECLARE_CTRLC_AST
+C
+C  SUBROUTINE DECLARE_CTRLC_AST
+C
+C  FUNCTION:
+C	Declares a CTRLC ast.
+C  NOTES:
+C	Assumes terminal assigned to TERM_CHAN in common /TERM_CHAN/.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	EXTERNAL IO$_SETMODE,IO$M_CTRLCAST,CTRLC_ROUTINE
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	FLAG = 0				! Init CTRL-C flag
+	IO_CTRLC = %LOC(IO$_SETMODE)+%LOC(IO$M_CTRLCAST)	! Set AST code
+	IER=SYS$QIOW(,%VAL(TERM_CHAN),%VAL(IO_CTRLC),,,,	! for QIO
+     &	      CTRLC_ROUTINE,,,,,)		! Enable the AST
+
+	RETURN
+
+	ENTRY CANCEL_CTRLC_AST
+
+	IER = SYS$CANCEL(%VAL(TERM_CHAN))
+
+	FLAG = 2		! Indicates that a CTRLC will cause an exit
+	IER=SYS$QIOW(,%VAL(TERM_CHAN),%VAL(IO_CTRLC),,,,	! for QIO
+     &	      CTRLC_ROUTINE,,,,,)		! Enable the AST
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_INPUT_NOECHO(DATA)
+C
+C  SUBROUTINE GET_INPUT_NOECHO
+C
+C  FUNCTION: Reads data in from terminal without echoing characters.
+C	     Also contains entry to assign terminal.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) DATA,PROMPT
+
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /READIT/ READIT
+
+	INCLUDE '($TRMDEF)'
+
+	INTEGER TERMSET(2)
+
+	INTEGER MASK(4)
+	DATA MASK/4*'FFFFFFFF'X/
+
+	DATA PURGE/.TRUE./
+
+	DO I=1,LEN(DATA)
+	   DATA(I:I) = ' '
+	END DO
+
+	IF (PURGE) THEN
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),
+     &		TRM$M_TM_NOECHO.OR.TRM$M_TM_PURGE)
+	   PURGE = .FALSE.
+	ELSE
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),
+     &		TRM$M_TM_NOECHO)
+	END IF
+
+	RETURN
+
+	ENTRY GET_INPUT_NOECHO_PROMPT(DATA,PROMPT)
+
+	DO I=1,LEN(DATA)
+	   DATA(I:I) = ' '
+	END DO
+
+	IF (PURGE) THEN
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,PROMPT,LEN(DATA),
+     &		TRM$M_TM_NOECHO.OR.TRM$M_TM_PURGE)
+	   PURGE = .FALSE.
+	ELSE
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,PROMPT,LEN(DATA),
+     &		TRM$M_TM_NOECHO)
+	END IF
+
+	RETURN
+
+	ENTRY GET_INPUT_NUM(DATA,NLEN)
+
+	DO I=1,LEN(DATA)
+	   DATA(I:I) = ' '
+	END DO
+
+	IF (PURGE) THEN
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),
+     &		TRM$M_TM_PURGE,,TERMSET,NLEN,TERM)
+	   PURGE = .FALSE.
+	ELSE
+	   CALL SMG$READ_STRING(KEYBOARD_ID,DATA,,LEN(DATA),,,
+     &		TERMSET,NLEN,TERM)
+	END IF
+
+	IF (TERM.NE.13.AND.TERM.NE.510.AND.NLEN.EQ.0) THEN
+				! Input did not end with CR or buffer full
+	   NLEN = 1
+	   DATA(:1) = CHAR(TERM)
+	END IF
+
+	RETURN
+
+	ENTRY ASSIGN_TERMINAL
+
+	IER = SYS$ASSIGN('TT',TERM_CHAN,,)	! Assign terminal
+
+	CALL DECLARE_CTRLC_AST
+
+	FLAG = 2		! Indicates that a CTRLC will cause an exit
+
+	IER = SMG$CREATE_VIRTUAL_KEYBOARD(KEYBOARD_ID,,,,20)
+
+	IER = SMG$CREATE_KEY_TABLE(KEY_TABLE_ID)
+
+	IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,0)
+
+	IF (CLI$PRESENT('KEYPAD')) THEN
+	   CALL SET_KEYPAD
+	ELSE IF (READIT.EQ.0) THEN
+	   CALL SET_NOKEYPAD
+	END IF
+
+	TERMSET(1) = 16
+	TERMSET(2) = %LOC(MASK)
+
+	DO I=ICHAR('0'),ICHAR('9')
+	   MASK(2) = IBCLR(MASK(2),I-32)
+	END DO
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GETPAGSIZ(PAGE_LENGTH,PAGE_WIDTH)
+C
+C  SUBROUTINE GETPAGSIZ
+C
+C  FUNCTION:
+C	Gets page size of the terminal.
+C
+C  OUTPUTS:
+C	PAGE_LENGTH  -  Page length of the terminal.
+C	PAGE_WIDTH   -  Page size of the terminal.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($DVIDEF)'
+
+	LOGICAL*1 DEVDEPEND(4)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,DVI$_DEVDEPEND,%LOC(DEVDEPEND(1)))
+	CALL ADD_2_ITMLST(4,DVI$_DEVBUFSIZ,%LOC(PAGE_WIDTH))
+	CALL END_ITMLST(GETDVI_ITMLST)		! Get address of itemlist
+
+	CALL SYS$GETDVIW(,,'TT',%VAL(GETDVI_ITMLST),,,,)
+
+	PAGE_LENGTH = ZEXT(DEVDEPEND(4))
+
+	PAGE_WIDTH = MIN(PAGE_WIDTH,132)
+
+	RETURN
+	END
+
+
+
+
+
+	LOGICAL FUNCTION SLOW_TERMINAL
+C
+C  FUNCTION SLOW_TERMINAL
+C
+C  FUNCTION:
+C	Indicates that terminal has a slow speed (2400 baud or less).
+C
+C  OUTPUTS:
+C	SLOW_TERMINAL = .true. if slow, .false. if not.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	EXTERNAL IO$_SENSEMODE
+
+	COMMON /TERM_CHAN/ TERM_CHAN
+
+	COMMON CHAR_BUF(2)
+
+	LOGICAL*1 IOSB(8)
+
+	INCLUDE '($TTDEF)'
+
+	IER = SYS$QIOW(,%VAL(TERM_CHAN),IO$_SENSEMODE,IOSB,,,
+     &		  CHAR_BUF,%VAL(8),,,,)
+
+	IF (IOSB(3).LE.TT$C_BAUD_2400.AND.IOSB(3).NE.0) THEN
+	   SLOW_TERMINAL = .TRUE.
+	ELSE
+	   SLOW_TERMINAL = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOW_PRIV
+C
+C  SUBROUTINE SHOW_PRIV
+C
+C  FUNCTION:
+C	To show privileges necessary for managing bulletin board.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /PRVDEF/ PRIVS
+	CHARACTER*8 PRIVS(0:38)
+
+	CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+
+	CALL READ_USER_FILE_HEADER(IER)
+
+	IF (IER.EQ.0) THEN			! If header is present, exit
+	   IF (NEW_FLAG(1).EQ.-1.AND.NEW_FLAG(2).EQ.-1) THEN  ! Info not present
+	      CALL CLOSE_BULLUSER
+	      CALL OPEN_BULLUSER			! Get BULLUSER.DAT file
+	      CALL READ_USER_FILE_HEADER(IER)
+	      USERPRIV(1) = PRV$M_OPER.OR.PRV$M_CMKRNL.OR.PRV$M_SETPRV
+	      USERPRIV(2) = 0
+	      REWRITE (4) USER_HEADER
+	   END IF
+	   WRITE (6,'('' Following privileges are needed for privileged
+     & commands:'')')
+	   DO I=0,38
+	      IF ((I.LT.32.AND.BTEST(USERPRIV(1),I)).OR.
+     &		  (I.GT.31.AND.BTEST(USERPRIV(2),I-32))) THEN
+		 WRITE (6,'(1X,A)') PRIVS(I)
+	      END IF
+	   END DO
+	ELSE
+	   WRITE (6,'('' ERROR: Cannot show privileges.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER			! All finished with BULLUSER
+
+	CALL CHKACL(BULLUSER_FILE(:TRIM(BULLUSER_FILE)),IER)
+	IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.IER) THEN
+	   CALL SHOWACL(BULLUSER_FILE(:TRIM(BULLUSER_FILE)))
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE SET_PRIV
+C
+C  SUBROUTINE SET_PRIV
+C
+C  FUNCTION:
+C	To set privileges necessary for managing bulletin board.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	COMMON /PRVDEF/ PRIVS
+	CHARACTER*8 PRIVS(0:38)
+	DATA PRIVS
+     &	/'CMKRNL','CMEXEC','SYSNAM','GRPNAM','ALLSPOOL','DETACH',
+     &  'DIAGNOSE','LOG_IO','GROUP','ACNT','PRMCEB','PRMMBX','PSWAPM',
+     &	'ALTPRI','SETPRV','TMPMBX','WORLD','MOUNT','OPER','EXQUOTA',
+     &	'NETMBX','VOLPRO','PHY_IO','BUGCHK','PRMGBL','SYSGBL','PFNMAP',
+     &	'SHMEM','SYSPRV','BYPASS','SYSLCK','SHARE','UPGRADE','DOWNGRADE',
+     &	'GRPPRV','READALL',' ',' ','SECURITY'/
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	DIMENSION ONPRIV(2),OFFPRIV(2)
+
+	CHARACTER*32 INPUT_PRIV
+
+	IF (.NOT.SETPRV_PRIV().OR..NOT.BTEST(PROCPRIV(1),PRV$V_SETPRV)) THEN
+	   WRITE (6,'('' ERROR: This command requires SETPRV privileges.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('ID').OR.
+     &		CLI$PRESENT('ID').EQ.%LOC(CLI$_NEGATED)) THEN
+	   DO WHILE (CLI$GET_VALUE('PRIVILEGES',INPUT_PRIV,PLEN)
+     &	       .NE.%LOC(CLI$_ABSENT))		! Get the IDs
+	      IF (CLI$PRESENT('ID')) THEN
+		 CALL ADD_ACL(INPUT_PRIV(:PLEN),'R+C',IER)
+	      ELSE
+		 CALL DEL_ACL(INPUT_PRIV(:PLEN),'R+C',IER)
+	      END IF
+	      IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   END DO
+	   RETURN
+	END IF
+
+	OFFPRIV(1) = 0
+	OFFPRIV(2) = 0
+	ONPRIV(1) = 0
+	ONPRIV(2) = 0
+
+	DO WHILE (CLI$GET_VALUE('PRIVILEGES',INPUT_PRIV,PLEN)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the privileges
+	   PRIV_FOUND = -1
+	   I = 0
+	   DO WHILE (I.LT.39.AND.PRIV_FOUND.EQ.-1)
+	      IF (INPUT_PRIV(:PLEN).EQ.PRIVS(I)) PRIV_FOUND = I
+	      IF (INPUT_PRIV(3:PLEN).EQ.PRIVS(I)) PRIV_FOUND = I
+	      I = I + 1
+	   END DO
+	   IF (PRIV_FOUND.EQ.-1) THEN
+	      WRITE(6,'('' ERROR: Incorrectly specified privilege = '',
+     &		A)') INPUT_PRIV(:PLEN)
+	      RETURN
+	   ELSE IF (INPUT_PRIV(:2).EQ.'NO') THEN
+	      IF (INPUT_PRIV.EQ.'NOSETPRV') THEN
+	       WRITE(6,'('' ERROR: Cannot remove SETPRV privileges.'')')
+	       RETURN
+	      ELSE IF (PRIV_FOUND.LT.32) THEN
+		 OFFPRIV(1) = IBSET(OFFPRIV(1),PRIV_FOUND)
+	      ELSE
+		 OFFPRIV(2) = IBSET(OFFPRIV(2),PRIV_FOUND-32)
+	      END IF
+	   ELSE
+	      IF (PRIV_FOUND.LT.32) THEN
+		 ONPRIV(1) = IBSET(ONPRIV(1),PRIV_FOUND)
+	      ELSE
+		 ONPRIV(2) = IBSET(ONPRIV(2),PRIV_FOUND-32)
+	      END IF
+	   END IF
+	END DO
+
+	CALL OPEN_BULLUSER		! Get BULLUSER.DAT file
+
+	CALL READ_USER_FILE_HEADER(IER)
+
+	IF (IER.EQ.0) THEN			! If header is present, exit
+	   USERPRIV(1) = USERPRIV(1).OR.ONPRIV(1)
+	   USERPRIV(2) = USERPRIV(2).OR.ONPRIV(2)
+	   USERPRIV(1) = USERPRIV(1).AND.(.NOT.OFFPRIV(1))
+	   USERPRIV(2) = USERPRIV(2).AND.(.NOT.OFFPRIV(2))
+	   REWRITE (4) USER_HEADER
+	   WRITE (6,'('' Privileges successfully modified.'')')
+	ELSE
+	   WRITE (6,'('' ERROR: Cannot modify privileges.'')')
+	END IF
+
+	CALL CLOSE_BULLUSER			! All finished with BULLUSER
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE ADD_ACL(ID,ACCESS,IER)
+C
+C  SUBROUTINE ADD_ACL
+C
+C  FUNCTION: Adds ACL to bulletin files.
+C
+C  PARAMETERS:
+C	ID - Character string containing identifier to add to ACL.
+C	ACCESS - Character string containing access controls to give to ID.
+C	IER - Return error from attempting to set ACL.
+C
+C  NOTE: The ID must be in the RIGHTS data base.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /ACL/ ACLENT
+	CHARACTER ACLENT*256
+
+	CHARACTER ID*(*),ACCESS*(*),NEWS_ACCESS*132
+
+	INCLUDE '($ACLDEF)'
+
+	INCLUDE '($SSDEF)'
+
+	IER = SYS$PARSE_ACL('(IDENTIFIER='//ID//',ACCESS='
+     &	   //ACCESS//')',ACLENT,,)
+	IF (.NOT.IER) THEN
+	   IF (IER.EQ.SS$_NOSUCHID.AND.ADDID.AND.
+     &				INDEX(ACCESS,'C').EQ.0) THEN
+	      CALL GET_UAF(ID,USER,GROUP,ACCOUNT,FLAGS,IER)
+	      IF (.NOT.IER) THEN
+		 CALL ERRSNS(IDUMMY,IER)
+		 WRITE (6,'(
+     &		    '' ERROR: Specified username cannot be verified.'')')
+		 CALL SYS_GETMSG(IER)
+	         RETURN
+	      END IF
+	      IDENT = USER + ISHFT(GROUP,16)
+	      IER = SYS$ADD_IDENT(ID,%VAL(IDENT),,)
+	      IF (IER) THEN
+	         IER = SYS$PARSE_ACL('(IDENTIFIER='//ID//',ACCESS='
+     &	           //ACCESS//')',ACLENT,,)
+	      END IF
+	   END IF
+	END IF
+	IF (.NOT.IER) RETURN
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_ADDACLENT,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IF (INDEX(ACCESS,'C').GT.0.AND.INDEX(ACCESS,'W').EQ.0) THEN
+	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,BULLUSER_FILE(:TRIM(
+     &		   BULLUSER_FILE)),%VAL(ACL_ITMLST),,,)
+	   RETURN
+	END IF
+
+	IF (INDEX(FOLDER1,'.').GT.0) THEN
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,NEWS_ACCESS(FOLDER1_DESCRIP)
+     &	      ,%VAL(ACL_ITMLST),,,)
+        ELSE
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,FOLDER1_FILE
+     &	      (:TRIM(FOLDER1_FILE))//'.BULLFIL',%VAL(ACL_ITMLST),,,)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DEL_ACL(ID,ACCESS,IER)
+C
+C  SUBROUTINE DEL_ACL
+C
+C  FUNCTION: Adds ACL to bulletin files.
+C
+C  PARAMETERS:
+C	ID - Character string containing identifier to add to ACL.
+C	ACCESS - Character string containing access controls to give to ID.
+C	IER - Return error from attempting to set ACL.
+C
+C  NOTE: The ID must be in the RIGHTS data base.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /ACL/ ACLENT
+	CHARACTER ACLENT*256
+
+	CHARACTER ID*(*),ACCESS*(*),NEWS_ACCESS*132
+
+	INCLUDE '($ACLDEF)'
+
+	IF (ID.NE.' ') THEN
+	   IER = SYS$PARSE_ACL('(IDENTIFIER='//ID//',ACCESS='
+     &	      //ACCESS//')',ACLENT,,)
+	   IF (.NOT.IER) RETURN
+
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_DELACLENT,%LOC(ACLENT))
+	   CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	ELSE
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(255,ACL$C_DELETEACL,%LOC(ACLENT))
+	   CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	END IF
+
+	IF (INDEX(ACCESS,'C').GT.0) THEN
+	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,BULLUSER_FILE(:TRIM(
+     &		   BULLUSER_FILE)),%VAL(ACL_ITMLST),,,)
+	   RETURN
+	END IF
+
+	IF (INDEX(FOLDER1,'.').GT.0) THEN
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,NEWS_ACCESS(FOLDER1_DESCRIP)
+     &	      ,%VAL(ACL_ITMLST),,,)
+        ELSE
+  	   IER = SYS$CHANGE_ACL(,ACL$C_FILE,FOLDER1_FILE
+     &	      (:TRIM(FOLDER1_FILE))//'.BULLFIL',%VAL(ACL_ITMLST),,,)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CREATE_FOLDER
+C
+C  SUBROUTINE CREATE_FOLDER
+C
+C  FUNCTION: Creates a new bulletin folder.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	DATA REMOTE_SET /.FALSE./
+
+	COMMON /BULL_CUSTOM/ BULL_CUSTOM
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	DIMENSION LAST(2,FOLDER_MAX)
+	INTEGER*2 LAST2(4,FOLDER_MAX)
+	EQUIVALENCE (LAST,LAST2)
+
+	CHARACTER RESPONSE*4
+
+	IF (CLI$PRESENT('NEWS')) THEN
+	   CALL CREATE_NEWS_FOLDER
+	   RETURN
+	END IF
+
+	IF (.NOT.SETPRV_PRIV().AND.(CLI$PRESENT('NEEDPRIV').OR.
+     &		BTEST(BULL_CUSTOM,0))) THEN
+	   WRITE(6,'('' ERROR: CREATE is a privileged command.'')')
+	   RETURN
+	END IF
+
+	IER = CLI$GET_VALUE('CREATE_FOLDER',FOLDER,LEN_T) ! Get folder name
+	CALL STR$UPCASE(FOLDER,FOLDER)
+
+	IF (LEN_T.GT.44) THEN
+	   WRITE(6,'('' ERROR: Folder name must be < 45 characters.'')')
+	   RETURN
+	END IF
+
+	IF (.NOT.SETPRV_PRIV().AND.(CLI$PRESENT('ALWAYS').OR.
+     &	     CLI$PRESENT('NOTIFY').OR.CLI$PRESENT('READNEW').OR.
+     &	     CLI$PRESENT('BRIEF').OR.CLI$PRESENT('SYSTEM'))) THEN
+	   WRITE (6,'('' ERROR: Privileged qualifier specified.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$PRESENT('NODE')) THEN	! Remote node specified?
+	   IER = CLI$GET_VALUE('NODE',FOLDER_BBOARD,LEN_B) ! Get node name
+	   FOLDER_BBOARD = '::'//FOLDER_BBOARD(:LEN_B)
+	   FOLDER1_BBOARD = FOLDER_BBOARD
+	   IF (.NOT.CLI$GET_VALUE('REMOTENAME',FOLDER1,LEN_P)) THEN
+	      FOLDER1 = FOLDER
+	   ELSE IF (LEN_P.GT.40) THEN
+	      WRITE (6,'('' ERROR: REMOTENAME cannot be longer '',
+     &			 ''than 40 characters.'')')
+	   END IF
+	   FOLDER1_NUMBER = FOLDER_MAX
+	   CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	   IF (IER.NE.0) THEN
+	    WRITE (6,'('' ERROR: Folder not accessible on remote node.'')')
+	    RETURN
+	   ELSE IF (CLI$PRESENT('SYSTEM').AND.
+     &				.NOT.BTEST(FOLDER1_FLAG,2)) THEN
+	    WRITE (6,'('' ERROR: /SYSTEM not allowed as remote node'',
+     &			'' is not SYSTEM folder.'')')
+	    RETURN
+	   END IF
+	END IF
+
+	LENDES = 0
+	DO WHILE (LENDES.EQ.0)
+	   IF (CLI$PRESENT('DESCRIPTION')) THEN		! DESCRIPTION specified?
+	      IER = CLI$GET_VALUE('DESCRIPTION',FOLDER_DESCRIP,LENDES)
+	   ELSE
+	      WRITE (6,'('' Enter one line description of folder.'')')
+	      CALL GET_LINE(FOLDER_DESCRIP,LENDES)	! Get input line
+	      FOLDER_DESCRIP = FOLDER_DESCRIP(:LENDES)	! End fill with spaces
+	   END IF
+	   IF (LENDES.LE.0) THEN
+	      WRITE (6,'('' Aborting folder creation.'')')
+	      RETURN
+	   ELSE IF (LENDES.GT.80) THEN		! If too many characters
+	      WRITE(6,'('' ERROR: folder must be < 80 characters.'')')
+	      RETURN
+	   END IF
+	END DO
+
+	CALL OPEN_BULLFOLDER		! Open folder file
+	READ (7,IOSTAT=IER,KEY=FOLDER,KEYID=0)
+					! See if folder exists
+
+	IF (IER.EQ.0) THEN
+	   WRITE (6,'('' ERROR: Specified folder already exists.'')')
+	   GO TO 1000
+	END IF
+
+	IF (CLI$PRESENT('OWNER')) THEN
+	   IF (.NOT.SETPRV_PRIV().AND..NOT.CLI$PRESENT('ID')) THEN
+	      WRITE (6,'('' ERROR: /OWNER requires privileges.'')')
+	      CALL CLOSE_BULLFOLDER
+	      RETURN
+	   ELSE
+	      CALL CLI$GET_VALUE('OWNER',FOLDER1_OWNER,LEN_P)
+	      IF (LEN_P.GT.12) THEN
+	         WRITE (6,'('' ERROR: Folder owner name must be'',
+     &		        '' no more than 12 characters long.'')')
+	         CALL CLOSE_BULLFOLDER
+	         RETURN
+	      ELSE IF (CLI$PRESENT('ID')) THEN
+		 IER = CHKPRO(FOLDER1_OWNER)
+	         IF (.NOT.IER) THEN
+	            WRITE (6,'('' ERROR: ID not valid.'')')
+	            CALL CLOSE_BULLFOLDER
+	            RETURN
+		 END IF
+	      ELSE
+	         CALL GET_UAF
+     &		   (FOLDER1_OWNER,USERB1,GROUPB1,ACCOUNTB1,FLAGS,IER)
+	         IF (.NOT.IER) THEN
+	            WRITE (6,'('' ERROR: Owner not valid username.'')')
+	            CALL CLOSE_BULLFOLDER
+	            RETURN
+		 END IF
+	      END IF
+	      FOLDER_OWNER = FOLDER1_OWNER
+	   END IF
+	ELSE
+	   FOLDER_OWNER = USERNAME		! Get present username
+	   FOLDER1_OWNER = FOLDER_OWNER		! Save for later
+	END IF
+
+	FOLDER_SET = .TRUE.
+
+	CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+			! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD,GROUP)
+
+C
+C  Folder file is placed in the directory FOLDER_DIRECTORY.
+C  The file prefix is the name of the folder.
+C
+
+	FD_LEN = TRIM(FOLDER_DIRECTORY)
+	IF (FD_LEN.EQ.0) THEN
+	 WRITE (6,'('' ERROR: System programmer has disabled folders.'')')
+	 GO TO 910
+	ELSE
+	 FOLDER_FILE = FOLDER_DIRECTORY(:FD_LEN)//FOLDER
+	END IF
+
+	OPEN (UNIT=2,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Cannot create folder directory file.'')')
+	   CALL ERRSNS(IDUMMY,IER)
+	   CALL SYS_GETMSG(IER)
+	   GO TO 910
+	END IF
+
+	OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     1	 //'.BULLFIL',STATUS='NEW',
+     1	 ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     1	 FORM='UNFORMATTED',IOSTAT=IER)
+
+	IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Cannot create folder message file.'')')
+	   CALL ERRSNS(IDUMMY,IER)
+	   CALL SYS_GETMSG(IER)
+	   GO TO 910
+	END IF
+
+	FOLDER_FLAG = 0
+
+	IF (CLI$PRESENT('PRIVATE').OR.CLI$PRESENT('SEMIPRIVATE')) THEN
+				! Will folder have access limitations?
+	   FOLDER1_FILE = FOLDER_FILE
+	   CLOSE (UNIT=1)
+	   CLOSE (UNIT=2)
+	   FOLDER1 = FOLDER	! Save for ADD_ACL
+	   IF (CLI$PRESENT('SEMIPRIVATE')) THEN
+	      CALL ADD_ACL('*','R',IER)
+	   ELSE
+	      CALL ADD_ACL('*','NONE',IER)
+	   END IF
+	   CALL ADD_ACL(FOLDER_OWNER,'R+W+C',IER)
+	   OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     1	    //'.BULLDIR',STATUS='OLD',IOSTAT=IER1)
+	   OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     1	    //'.BULLFIL',STATUS='OLD',IOSTAT=IER1)
+	   IF (.NOT.IER) THEN
+	      WRITE(6,
+     &	      '('' ERROR: Cannot create private folder using ACLs.'')')
+	      CALL SYS_GETMSG(IER)
+	      GO TO 910
+	   END IF
+	   FOLDER_FLAG = IBSET(FOLDER_FLAG,0)
+	END IF
+
+	IER = 0
+	LAST_NUMBER = 1
+	DO WHILE (IER.EQ.0.AND.LAST_NUMBER.LT.FOLDER_MAX-1)
+	   READ (7,IOSTAT=IER,KEY=LAST_NUMBER,KEYID=1)
+	   LAST_NUMBER = LAST_NUMBER + 1
+	END DO
+
+	IF (IER.EQ.0) THEN
+	 WRITE (6,'('' ERROR: Folder limit of '',I,'' has been reached.'')')
+     &			FOLDER_MAX
+	 WRITE (6,'('' Unable to add specified folder.'')')
+	 GO TO 910
+	ELSE
+	   FOLDER1_NUMBER = LAST_NUMBER - 1
+	END IF
+
+	IF (.NOT.CLI$PRESENT('NODE')) THEN
+	   FOLDER_BBOARD = 'NONE'
+	   IF (REMOTE_SET) CLOSE (UNIT=REMOTE_UNIT)
+	   REMOTE_SET = .FALSE.
+	   FOLDER_BBEXPIRE = 14
+	   F_NBULL = 0
+	   NBULL = 0
+	   F_NEWEST_BTIM(1) = 0
+	   F_NEWEST_BTIM(2) = 0
+	   F_NEWEST_NOSYS_BTIM(1) = 0
+	   F_NEWEST_NOSYS_BTIM(2) = 0
+	   F_EXPIRE_LIMIT = 0
+	   FOLDER_NUMBER = FOLDER1_NUMBER
+	ELSE
+	   CLOSE (UNIT=1,STATUS='DELETE')
+	   CLOSE (UNIT=2,STATUS='DELETE')
+	   IF (FOLDER1.NE.FOLDER) THEN	! Different remote folder name?
+	      REMOTE_SET = .FALSE.
+    	      CALL OPEN_BULLDIR		! If so, store name in directory file
+	      BULLDIR_HEADER(13:) = FOLDER1
+	      CALL WRITEDIR_NOCONV(0,IER)
+	      CALL CLOSE_BULLDIR
+	      FOLDER1_BBOARD = FOLDER1_BBOARD(:LEN_B+2)//'*'
+	      FOLDER1 = FOLDER
+	   END IF
+	   REMOTE_SET = .TRUE.
+	   IF (BTEST(FOLDER1_FLAG,0)) FOLDER_FLAG = IBSET(FOLDER_FLAG,0)
+	   FOLDER1_FLAG = FOLDER_FLAG
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP
+	   FOLDER_COM = FOLDER1_COM
+	   NBULL = F_NBULL
+	END IF
+
+	FOLDER_NAME = FOLDER
+	FOLDER_OWNER = FOLDER1_OWNER
+
+	MAILTO = 0
+	I = INDEX(FOLDER_DESCRIP,'<')
+	J = INDEX(FOLDER_DESCRIP,'>')
+	IF (I.GT.0.AND.J.GT.I.AND.(INDEX(FOLDER_DESCRIP(I:),'@').LT.1.OR.
+     &	    INDEX(FOLDER_DESCRIP(I:),'@').GT.J-I+1).AND.NEWS_FEED()) THEN
+           FOLDER_FLAG = IBSET(FOLDER_FLAG,4)
+	   I = INDEX(FOLDER_DESCRIP,'[')
+	   J = INDEX(FOLDER_DESCRIP,']')
+	END IF
+
+	IF (I.GT.0.AND.J.GT.I.AND.
+     &	       (INDEX(FOLDER_DESCRIP(I:),'@').GT.1.AND.
+     &	       INDEX(FOLDER_DESCRIP(I:),'@').LT.J-I+1)) THEN
+	   MAILTO = 1
+	END IF
+
+	IF (CLI$PRESENT('SYSTEM')) FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	IF (CLI$PRESENT('ID')) FOLDER_FLAG = IBSET(FOLDER_FLAG,6)
+	IF (CLI$PRESENT('ALWAYS')) FOLDER_FLAG = IBSET(FOLDER_FLAG,7)
+	IF (CLI$PRESENT('POST_ONLY')) FOLDER_FLAG = IBSET(FOLDER_FLAG,10)
+	IF (CLI$PRESENT('ADD_ONLY')) FOLDER_FLAG = IBSET(FOLDER_FLAG,11)
+	IF (CLI$PRESENT('COMPRESS')) FOLDER_FLAG = IBSET(FOLDER_FLAG,12)
+
+	IF (I.GT.0.AND.J.GT.I.AND..NOT.NEWS_FEED().AND.MAILTO.EQ.0
+     &	    .AND..NOT.BTEST(FOLDER_FLAG,11)
+     &	    .AND..NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	   CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Have you specified '//
+     &		'an email address in the description? (default=N) ')
+	   IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') MAILTO = 1
+	END IF
+
+	IF (MAILTO.EQ.1.AND..NOT.BTEST(FOLDER_FLAG,11).AND.
+     &	    .NOT.BTEST(FOLDER_FLAG,10)) THEN 
+	   WRITE (6,'('' A mailing address has been specified.'')')
+	   CALL GET_INPUT_PROMPT(RESPONSE,RLEN,'Will messages be '//
+     &		'sent to and received from this address? (default=N) ')
+	   IF (RESPONSE(:1).EQ.'y'.OR.RESPONSE(:1).EQ.'Y') THEN
+	      MAILTO = 2
+	      WRITE (6,'('' SET POST_ONLY will be issued.'')')
+	   ELSE
+	      MAILTO = 3
+	      WRITE (6,'('' SET ADD_ONLY will be issued.'')')
+	   END IF
+	END IF
+
+	CALL WRITE_FOLDER_FILE(IER)
+	CALL MODIFY_SYSTEM_LIST(0)
+
+	CLOSE (UNIT=1)
+	CLOSE (UNIT=2)
+
+	NOTIFY = 0
+	READNEW = 0
+	BRIEF = 0
+	IF (CLI$PRESENT('NOTIFY')) NOTIFY = 1
+	IF (CLI$PRESENT('READNEW')) READNEW = 1
+	IF (CLI$PRESENT('SHOWNEW')) BRIEF = 1
+	IF (CLI$PRESENT('BRIEF')) THEN
+	   BRIEF = 1
+	   READNEW = 1
+	END IF
+	CALL SET_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+
+	WRITE (6,'('' Folder is now set to '',A)')
+     &		FOLDER(:TRIM(FOLDER))//'.'
+
+	IF (CLI$GET_VALUE('COPY',FOLDER1,FLEN).NE.%LOC(CLI$_ABSENT)) THEN
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' Unable to copy folder settings.'')')
+	   ELSE
+	      CALL OPEN_BULLINF_SHARED
+	      IER = 0
+	      DO WHILE (IER.EQ.0)
+		 DO WHILE (REC_LOCK(IER))
+		    READ (9,IOSTAT=IER) TEMP_USER,LAST
+		 END DO
+		 IF (IER.EQ.0) THEN
+		    LU = TRIM(TEMP_USER)
+		    I = MAX(LU,2) - 1
+		    IF (.NOT.BTEST(ICHAR(TEMP_USER(I:I)),7)) THEN
+		       LAST(1,FOLDER1_NUMBER+1) = LAST(1,FOLDER_NUMBER+1)
+		       LAST(2,FOLDER1_NUMBER+1) = LAST(2,FOLDER_NUMBER+1)
+		       REWRITE (9,IOSTAT=IER) TEMP_USER,LAST 
+		    END IF
+		 END IF
+	      END DO
+	      CALL CLOSE_BULLINF
+	      CALL OPEN_BULLUSER_SHARED
+	      CALL READ_USER_FILE_HEADER(IER)
+	      CALL READ_USER_FILE(IER)
+	      DO WHILE (IER.EQ.0)
+	         IF (TEST2(SET_FLAG,FOLDER1_NUMBER)) THEN
+		    CALL SET2(SET_FLAG,FOLDER_NUMBER)
+		 ELSE
+		    CALL CLR2(SET_FLAG,FOLDER_NUMBER)
+		 END IF
+	         IF (TEST2(BRIEF_FLAG,FOLDER1_NUMBER)) THEN
+		    CALL SET2(BRIEF_FLAG,FOLDER_NUMBER)
+		 ELSE
+		    CALL CLR2(BRIEF_FLAG,FOLDER_NUMBER)
+		 END IF
+	         IF (TEST2(NOTIFY_FLAG,FOLDER1_NUMBER)) THEN
+		    CALL SET2(NOTIFY_FLAG,FOLDER_NUMBER)
+		 ELSE
+		    CALL CLR2(NOTIFY_FLAG,FOLDER_NUMBER)
+		 END IF
+	         REWRITE(4) TEMP_USER//USER_ENTRY(13:)
+	         CALL READ_USER_FILE(IER)
+	      END DO
+	      CALL CLOSE_BULLUSER
+	   END IF
+	END IF
+
+	GO TO 1000
+
+910	WRITE (6,'('' Aborting folder creation.'')')
+	IF (FOLDER_NUMBER.EQ.0) FOLDER_SET = .FALSE.
+	CLOSE (UNIT=1,STATUS='DELETE')
+	CLOSE (UNIT=2,STATUS='DELETE')
+
+1000	CALL CLOSE_BULLFOLDER
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	RETURN
+
+	END
+
+
+
+	INTEGER FUNCTION CHKPRO(INPUT)
+C
+C 	Description:
+C		Parse given identify into binary ACL format.
+C		Call SYS$CHKPRO to check if present process has read
+C		access to an object if the object's protection is the ACL.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER ACL*256
+	CHARACTER*(*) INPUT
+
+	INCLUDE '($CHPDEF)'
+
+	CHKPRO = SYS$PARSE_ACL('(IDENTIFIER='//INPUT(:TRIM(INPUT))//
+     &		',ACCESS=R)',ACL,,)	! Convert to ACL into binary format
+	IF (.NOT.CHKPRO) RETURN		! Exit if can't
+
+	FLAGS = CHP$M_READ		! Specify read access checking
+
+	CALL INIT_ITMLST		! Initialize item list
+	CALL ADD_2_ITMLST(ICHAR(ACL(:1)),CHP$_ACL,%LOC(ACL(1:1)))
+	CALL ADD_2_ITMLST(4,CHP$_FLAGS,%LOC(FLAGS))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	CHKPRO = SYS$CHKPRO(%VAL(ACL_ITMLST))	! Check if process has the
+						! rights-id assigned to it
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CREATE_NEWS_FOLDER
+C
+C  SUBROUTINE CREATE_NEWS_FOLDER
+C
+C  FUNCTION: Creates a new newsgroup.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /EDIT/ EDIT_DEFAULT
+	DATA EDIT_DEFAULT/.FALSE./
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	EDITIT = (CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.
+     &           (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))
+
+	IER = CLI$GET_VALUE('CREATE_FOLDER',FOLDER1_NAME,LEN_F)
+	CALL LOWERCASE(FOLDER1_NAME)
+
+	LEN_P = 0
+
+	IF (CLI$PRESENT('FILESPEC')) THEN
+	   IER = CLI$GET_VALUE('FILESPEC',BULL_PARAMETER,LEN_P)
+	   CALL DISABLE_PRIVS
+	   OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
+     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
+	   CALL ENABLE_PRIVS	! Reset SYSPRV privileges
+	END IF
+C
+C  If file specified in command, read file.
+C  Else, read  from the terminal.
+C
+
+	IF (EDITIT) THEN			! If /EDIT specified
+	   IF (LEN_P.EQ.0) THEN			! If no file param specified
+	      CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 DISPOSE='DELETE',ERR=910,FORM='FORMATTED')
+	      LEN_P = 1
+	   ELSE
+	      CLOSE (UNIT=3)
+	      CALL MAILEDIT(BULL_PARAMETER(:LEN_P),'SYS$LOGIN:BULL.SCR')
+	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
+     &		 DISPOSE='DELETE',ERR=910,FORM='FORMATTED')
+	   END IF
+	ELSE IF (LEN_P.EQ.0) THEN			! If file param
+	   OPEN (UNIT=3,STATUS='SCRATCH',FILE='SYS$LOGIN:BULL.SCR',
+     &		FORM='FORMATTED',RECL=LINE_LENGTH) ! Temp file to save message
+	   WRITE (6,1000)			! Request input from terminal
+1000	   FORMAT (' Enter newsgroup description:',
+     &		   ' End with ctrl-z, cancel with ctrl-c')
+	   ILEN = 0
+	   ICOUNT = 0
+	   DO WHILE (ILEN.GE.0)			! Input until no more input
+	      CALL GET_LINE(INPUT,ILEN)		! Get input line
+	      IF (ILEN.GT.LINE_LENGTH) THEN	! Input line too long
+		 WRITE(6,'('' ERROR: Input line length > '',I,
+     &			''.  Reinput:'')') LINE_LENGTH
+	      ELSE IF (ILEN.GE.0) THEN		! If good input line entered
+		 WRITE(3,2010) INPUT(:ILEN)	! Save line in scratch file
+2010	         FORMAT(A)
+		 ICOUNT = ICOUNT + ILEN
+	      END IF
+	   END DO
+	   IF (ILEN.EQ.-1) GO TO 910		! CTRL_C entered, error out
+	   IF (ICOUNT.EQ.0) GO TO 910		! No lines entered, error out
+	ENDIF
+
+	REWIND (UNIT=3)
+
+	CALL NEWS_POST('newgroup '//FOLDER1_NAME(:LEN_F),.TRUE.,IER,
+     &		       'Adding newsgroup.')
+	CLOSE (UNIT=3)
+
+	RETURN
+
+920	WRITE(6,1020)
+1020	FORMAT (' ERROR: Unable to open specified file.')
+	CALL ENABLE_PRIVS
+	RETURN
+
+910	WRITE(6,1010)
+1010	FORMAT (' No news group was added.')
+	CLOSE (UNIT=3)
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE INIT_COMPRESS
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*2 MAP(159),UNMAP(0:254)
+
+	DATA MAP/
+     &	'  ', 'e ', 'th', ' t', 's ', ' a', 'in', 't ', 'er', 'he', 'on',
+     &	'at', ': ', 're', 'an', 'it', 'ti', 'n ', ' i', ' o', 'es', 'ne',
+     &	'te', 'd ', ' s', 'en', 'ed', 'is', 'ic', 'y ', 'st', 'ar', 'or',
+     &	', ', ' w', 'al', 'ou', 'ha', 'du', 'le', 'r ', 'nt', '.e', 'nd',
+     &	'to', 'f ', 've', 'ng', 'ct', ' p', 'o ', 'me', 'om', 'of', '. ',
+     &	' c', 'io', 'ri', 'ca', 'se', ' m', ' b', 'ta', 'co', 'el', 'si',
+     &	'as', 'hi', 'de', ' f', 'l ', 'ec', 'll', 'ro', 'et', 'a ', ' d',
+     &	'ni', ' e', 'ea', 'no', 'li', 'ch', 's.', 'ra', 'ma', 'ce', 'sc',
+     &	'ns', 'g ', 'ss', 'nc', 'us', 'be', ' h', '> ', 'h ', 'ac', 'os',
+     &	'ci', 'bl', 'ph', 'rt', ' r', 'ot', ' I', 'tr', 'ut', ' n', 'la',
+     &	'cs', 'ly', 'pr', 'wa', 'ws', 'oo', 'pe', 'ag', 'ys', 'so', 'ie',
+     &	'ur', 'un', ' (', 'po', 'fo', 'em', ' l', 'm ', 'ho', 'lo', 'wi',
+     &	' T', 'e.', 'im', 'di', 'ia', '.c', 'pa', 'ge', 'ga', 'ee', 'rs',
+     &	'pi', 'su', 'Th', 'il', 'ai', 'wh', 'ol', 'ul', 'gr', 'ow', 'u ',
+     &	'iv', 'pl', 'ab', 'am', 'mo'/
+
+	CHARACTER*1 A(0:127,0:127)
+	CHARACTER*2 B
+
+	CHARACTER*(*) IN,OUT
+	CHARACTER*255 T
+
+	DO I=0,127
+	   DO J=0,127
+	     A(J,I) = ' '
+	   END DO
+	END DO
+
+	UNMAP(0) = '  '
+        DO I=1,254
+           UNMAP(I) = CHAR(255)//CHAR(255)
+	END DO
+	
+	J = 1
+	DO I=1,8
+	   J = J + 1
+	   B = MAP(J)
+	   UNMAP(I) = B
+	   A(ICHAR(B(:1)),ICHAR(B(2:2))) = CHAR(I)
+	END DO
+	DO I=10,31
+	   J = J + 1
+	   B = MAP(J)
+	   UNMAP(I) = B
+	   A(ICHAR(B(:1)),ICHAR(B(2:2))) = CHAR(I)
+	END DO
+	DO I=127,254
+	   J = J + 1
+	   B = MAP(J)
+	   UNMAP(I) = B
+	   A(ICHAR(B(:1)),ICHAR(B(2:2))) = CHAR(I)
+	END DO
+
+	RETURN
+
+	ENTRY COMPRESS(IN,OUT,O)
+
+	L = LEN(IN)
+	O = 1
+	K = 1
+	DO WHILE (K.LT.L)
+	   IF (ICHAR(IN(K:K)).GT.126) IN(K:K) = ' '
+	   IF (ICHAR(IN(K+1:K+1)).GT.126) IN(K+1:K+1) = ' '
+	   T(O:O) = A(ICHAR(IN(K:)),ICHAR(IN(K+1:)))
+	   IF (T(O:O).NE.' ') THEN
+	      K = K + 2
+	      O = O + 1
+	   ELSE IF (L.GT.K+2.AND.IN(K:K).EQ.IN(K+1:K+1).AND.
+     &		    IN(K:K+1).EQ.IN(K+2:K+3)) THEN
+	      C = 4
+	      K = K + 4
+	      DO WHILE (K.LE.L.AND.IN(K:K).EQ.IN(K-1:K-1))
+		 C = C + 1
+		 K = K + 1
+	      END DO
+	      T(O:O+2) = CHAR(255)//CHAR(C)//IN(K-1:K-1)
+	      O = O + 3
+	   ELSE IF (IN(K:K+1).EQ.'  ') THEN
+	      K = K + 2
+	      T(O:O) = CHAR(0)
+	      O = O + 1
+	   ELSE
+	      T(O:O) = IN(K:K)
+	      IF (ICHAR(T(O:O)).LT.9.OR.(ICHAR(T(O:O)).GT.9.AND.
+     &		 ICHAR(T(O:O)).LT.32)) T(O:O) = ' '
+	      K = K + 1
+	      O = O + 1
+	   END IF
+	END DO
+	IF (K.EQ.L) THEN
+	   T(O:O) = IN(K:K)
+	ELSE
+	   O = O - 1
+	END IF
+
+	OUT = T
+
+	RETURN
+
+	ENTRY UNCOMPRESS(IN,OUT,O)
+
+	L = LEN(IN)
+	O = 0
+	I = 1
+	DO WHILE (I.LE.L)
+	   J = ICHAR(IN(I:I))
+	   IF (J.EQ.255) THEN
+	      DO J=1,ICHAR(IN(I+1:I+1))
+	         O = O + 1
+	         T(O:O) = IN(I+2:I+2)
+	      END DO
+	      I = I + 3
+           ELSE
+	      B = UNMAP(J)
+	      IF (B.EQ.CHAR(255)//CHAR(255)) THEN
+	         O = O + 1
+                 T(O:O) = IN(I:I)
+	      ELSE
+	         O = O + 2
+	         T(O-1:O) = B
+	      END IF
+	      I = I + 1
+	   END IF
+	END DO
+
+	OUT = T(:O)
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin5.for b/decus/vmslt98a/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..bc7c3a7346b93bbec4dab25713f606eb99f8e8dc
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin5.for
@@ -0,0 +1,2516 @@
+C
+C  BULLETIN5.FOR, Version 3/5/98
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+C
+	SUBROUTINE SET_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+C
+C  SUBROUTINE SET_FOLDER_DEFAULT
+C
+C  FUNCTION: Sets flag defaults for specified folder
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_NEGATED
+
+	IF (REMOTE_SET.GE.3) THEN
+	   CALL SET_NEWS_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+	   RETURN
+        ELSE IF (FOLDER_NUMBER.LT.0) THEN
+	   WRITE (6,'('' ERROR: Command is invalid for this folder.'')')
+	   RETURN
+	END IF
+
+	ALL = .FALSE.
+	DEFAULT = 0
+	NODEFAULT = 0
+
+	IF (INCMD(:3).EQ.'SET') THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	      WRITE (6,'(
+     &           '' ERROR: Privileges needed for changing defaults.'')')
+	      RETURN
+	   END IF
+	   ALL = CLI$PRESENT('ALL')
+	   DEFAULT = CLI$PRESENT('DEFAULT')
+	   NODEFAULT = CLI$PRESENT('NODEFAULT')
+	   CALL OPEN_BULLUSER_SHARED
+	   IF (CLI$PRESENT('PERMANENT')) THEN
+	      CALL SET_PERM(NOTIFY,READNEW,BRIEF)
+	   ELSE IF (CLI$PRESENT('NOPERMANENT')) THEN
+	      IF (NOTIFY.GE.0) CALL SET_PERM(0,-1,-1)
+	      IF (READNEW.GE.0.OR.BRIEF.GE.0) CALL SET_PERM(-1,0,0)
+	   END IF
+	ELSE
+	   CALL OPEN_BULLUSER_SHARED
+	END IF
+
+	CALL READ_USER_FILE_HEADER(IER)
+	IF (NODEFAULT) THEN
+	   IF (NOTIFY.NE.-1) CALL CLR2(NOTIFY_FLAG_DEF,FOLDER_NUMBER)
+	   IF (READNEW.NE.-1.OR.BRIEF.NE.-1) THEN
+	      CALL CLR2(SET_FLAG_DEF,FOLDER_NUMBER)
+	      CALL CLR2(BRIEF_FLAG_DEF,FOLDER_NUMBER)
+	   END IF
+	   REWRITE(4) USER_HEADER
+	ELSE IF (DEFAULT.EQ.0.OR.DEFAULT) THEN
+	   IF (NOTIFY.EQ.0) CALL CLR2(NOTIFY_FLAG_DEF,FOLDER_NUMBER)
+	   IF (NOTIFY.EQ.1) CALL SET2(NOTIFY_FLAG_DEF,FOLDER_NUMBER)
+	   IF (READNEW.EQ.0) CALL CLR2(SET_FLAG_DEF,FOLDER_NUMBER)
+	   IF (READNEW.EQ.1) CALL SET2(SET_FLAG_DEF,FOLDER_NUMBER)
+	   IF (BRIEF.EQ.0) CALL CLR2(BRIEF_FLAG_DEF,FOLDER_NUMBER)
+	   IF (BRIEF.EQ.1) CALL SET2(BRIEF_FLAG_DEF,FOLDER_NUMBER)
+	   REWRITE(4) USER_HEADER
+	END IF
+
+	IF (ALL.OR.(BRIEF.NE.-1.AND.NOTIFY.NE.-1.AND.READNEW.NE.-1)) THEN
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0)
+	      IF (TEMP_USER(:1).NE.'*'.AND.TEMP_USER(:1).NE.':') THEN
+	         IF (NOTIFY.EQ.0) CALL CLR2(NOTIFY_FLAG,FOLDER_NUMBER)
+	         IF (NOTIFY.EQ.1) CALL SET2(NOTIFY_FLAG,FOLDER_NUMBER)
+	         IF (READNEW.EQ.0) CALL CLR2(SET_FLAG,FOLDER_NUMBER)
+	         IF (READNEW.EQ.1) CALL SET2(SET_FLAG,FOLDER_NUMBER)
+	         IF (BRIEF.EQ.0) CALL CLR2(BRIEF_FLAG,FOLDER_NUMBER)
+	         IF (BRIEF.EQ.1) CALL SET2(BRIEF_FLAG,FOLDER_NUMBER)
+	         REWRITE(4) TEMP_USER//USER_ENTRY(13:)
+	      END IF
+	      CALL READ_USER_FILE(IER)
+	   END DO
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE READ_PERM
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /BULL_PERM/ SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	DIMENSION SET_PERM_FLAG(FLONG)
+	DIMENSION BRIEF_PERM_FLAG(FLONG)
+	DIMENSION NOTIFY_PERM_FLAG(FLONG)
+
+	COMMON /FLAG_ACCESS/ FLAG_ACCESS
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*PERM',IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	END DO
+
+	IF (IER.NE.0) THEN
+	   DO I=1,FLONG
+	      SET_PERM_FLAG(I) = 0
+	      BRIEF_PERM_FLAG(I) = 0
+	      NOTIFY_PERM_FLAG(I) = 0
+	   END DO
+	   BRIEF_PERM_FLAG(1) = 1	! SHOWNEW permanent for GENERAL folder
+	   WRITE (4,IOSTAT=IER)
+     &		'*PERM       ',
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	   CALL READ_USER_FILE_HEADER(IER)
+	   IF (.NOT.TEST2(SET_FLAG_DEF,0)) THEN
+	      CALL SET2(BRIEF_FLAG_DEF,0)
+	      REWRITE(4) USER_HEADER
+	   END IF
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0)
+	      IF (TEMP_USER(:1).NE.'*'.AND.TEMP_USER(:1).NE.':') THEN
+		 IF (.NOT.TEST2(SET_FLAG,0)) THEN
+		    CALL SET2(BRIEF_FLAG,0)
+	            REWRITE(4) TEMP_USER//USER_ENTRY(13:)
+	         END IF
+	      END IF
+	      CALL READ_USER_FILE(IER)
+	   END DO
+	ELSE
+	   UNLOCK 4
+	END IF
+
+	RETURN
+
+	ENTRY SET_PERM(NOTIFY,READNEW,BRIEF)
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*PERM',IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	END DO
+
+	IF (NOTIFY.EQ.0) CALL CLR2(NOTIFY_PERM_FLAG,FOLDER_NUMBER)
+	IF (NOTIFY.EQ.1) CALL SET2(NOTIFY_PERM_FLAG,FOLDER_NUMBER)
+	IF (READNEW.EQ.0) CALL CLR2(SET_PERM_FLAG,FOLDER_NUMBER)
+	IF (READNEW.EQ.1) CALL SET2(SET_PERM_FLAG,FOLDER_NUMBER)
+	IF (BRIEF.EQ.0) CALL CLR2(BRIEF_PERM_FLAG,FOLDER_NUMBER)
+	IF (BRIEF.EQ.1) CALL SET2(BRIEF_PERM_FLAG,FOLDER_NUMBER)
+
+	REWRITE (4,IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+
+	RETURN
+
+	ENTRY SET_USER_FLAG(NOTIFY,READNEW,BRIEF)
+
+	IF (.NOT.FLAG_ACCESS) THEN
+	   WRITE (6,'('' ERROR: Cannot set flags for protected'',
+     &	     '' folder without explicit access granted'',/,
+     &	     '' via SET ACCESS.  See HELP SET ACCESS for further''
+     &       '' information.'')')
+	   RETURN
+	END IF
+
+	IF (REMOTE_SET.GE.3) THEN
+ 	   IF (REMOTE_SET.EQ.3.AND.NOTIFY.EQ.1) THEN
+	      WRITE (6,'('' ERROR: NOTIFY is not valid for this folder.'')')
+	      RETURN
+	   END IF
+	   CALL NEWS_SET_USER_FLAG(NOTIFY,READNEW,BRIEF)
+	   RETURN
+	END IF
+
+	CALL OPEN_BULLUSER_SHARED
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='*PERM',IOSTAT=IER) TEMP_USER,
+     &		SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	END DO
+
+	CALL CLOSE_BULLUSER
+
+	IER = .TRUE.
+	IF (NOTIFY.EQ.0) THEN
+ 	   IF (TEST2(NOTIFY_PERM_FLAG,FOLDER_NUMBER)) THEN
+	      WRITE (6,'('' ERROR: NOTIFY is permanent for this folder.'')')
+	      RETURN
+	   ELSE
+	      CALL CHANGE_FLAG(0,4)
+	   END IF
+	ELSE IF (NOTIFY.EQ.1) THEN
+	   CALL CHANGE_FLAG(1,4)
+	   RETURN
+	ELSE IF (BRIEF.EQ.0.AND.READNEW.EQ.0.AND.
+     &	   (TEST2(SET_PERM_FLAG,FOLDER_NUMBER).OR.
+     &	   TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER))) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.0.AND.
+     &	   TEST2(SET_PERM_FLAG,FOLDER_NUMBER).AND.
+     &	   .NOT.TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER)) THEN
+	   IER = .FALSE.
+	ELSE IF (BRIEF.EQ.1.AND.READNEW.EQ.1.AND.
+     &	   (TEST2(SET_PERM_FLAG,FOLDER_NUMBER).XOR.
+     &	   TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER)))  THEN
+	   IER = .FALSE.
+	END IF
+
+	IF (IER) THEN
+	   IF (READNEW.GE.0) CALL CHANGE_FLAG(READNEW,2)
+	   IF (BRIEF.GE.0) CALL CHANGE_FLAG(BRIEF,3)
+	ELSE
+	   WRITE (6,'('' ERROR: PERMANENT flags exist for this folder.'')')
+	   WRITE (6,'('' Flags will be set to those permanent settings.'')')
+
+	   IF (TEST2(SET_PERM_FLAG,FOLDER_NUMBER)) THEN
+	      CALL CHANGE_FLAG(1,2)
+	   ELSE
+	      CALL CHANGE_FLAG(0,2)
+	   END IF
+
+	   IF (TEST2(BRIEF_PERM_FLAG,FOLDER_NUMBER)) THEN
+	      CALL CHANGE_FLAG(1,3)
+	   ELSE
+	      CALL CHANGE_FLAG(0,3)
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE REMOVE_FOLDER
+C
+C  SUBROUTINE REMOVE_FOLDER
+C
+C  FUNCTION: Removes a bulletin folder.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER RESPONSE*4,TEMP*80
+
+	IER = CLI$GET_VALUE('REMOVE_FOLDER',FOLDER1,LEN_T) ! Get folder name
+
+	IF (IER.EQ.%LOC(CLI$_ABSENT)) THEN
+	   IF (.NOT.FOLDER_SET) THEN
+	      WRITE (6,'('' ERROR: No folder specified.'')')
+	      RETURN
+	   ELSE
+	      FOLDER1 = FOLDER
+	   END IF
+	ELSE IF (LEN_T.GT.44) THEN
+	   WRITE(6,'('' ERROR: Folder name must be < 26 characters.'')')
+	   RETURN
+	END IF
+
+	CALL GET_INPUT_PROMPT(RESPONSE,LEN,
+     &   'Are you sure you want to remove folder '
+     &	 //FOLDER1(:TRIM(FOLDER1))//' (Y/N with N as default): ')
+	IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+	   WRITE (6,'('' Folder was not removed.'')')
+	   RETURN
+	END IF
+
+	IF (INDEX(FOLDER1,'.').GT.0) THEN
+	   CALL OPEN_BULLNEWS_SHARED
+	ELSE
+	   CALL OPEN_BULLFOLDER
+	END IF
+
+	CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)	! See if folder exists
+	CALL SET_FOLDER_FILE(1)
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: No such folder exists.'')')
+	   GO TO 1000
+	ELSE IF (INDEX(FOLDER1,'.').GT.0) THEN
+	   CALL REMOTE_REMOVE_FOLDER(IER)
+	   IF (.NOT.IER) GO TO 1000
+	END IF
+
+	IF (.NOT.FOLDER_ACCESS(USERNAME,FOLDER1_FLAG,FOLDER1_OWNER).OR.
+     &	     (FOLDER1_NUMBER.EQ.0.AND.FOLDER1_BBOARD(:2).NE.'::')) THEN
+	   WRITE (6,'('' ERROR: You are not able to remove the folder.'')')
+	   GO TO 1000
+	END IF
+
+	TEMP = FOLDER_FILE
+	FOLDER_FILE = FOLDER1_FILE
+
+	REMOTE_SET_SAVE = REMOTE_SET
+	REMOTE_SET = .FALSE.
+
+	IF (FOLDER1_BBOARD(:2).EQ.'::'.AND.BTEST(FOLDER1_FLAG,2)) THEN
+	   FLEN = TRIM(FOLDER1_BBOARD)
+	   IF (INDEX(FOLDER1_BBOARD,'*').GT.0) FLEN = FLEN - 1
+	   OPEN (UNIT=17,STATUS='UNKNOWN',IOSTAT=IER,
+     &		RECL=256,FILE=FOLDER1_BBOARD(3:FLEN)
+     &		//'::"TASK=BULLETIN1"')
+	   IF (IER.EQ.0) THEN		! Deregister remote SYSTEM folder
+	      IF (INDEX(FOLDER1_BBOARD,'*').GT.0) THEN
+	         CALL OPEN_BULLDIR
+	         CALL READDIR(0,IER)
+		 IF (IER.EQ.1) FOLDER1 = BULLDIR_HEADER(13:)
+		 CALL CLOSE_BULLDIR
+	      END IF
+	      WRITE (17,'(2A)',IOSTAT=IER) 1,FOLDER1	! Select folder
+	      IF (IER.EQ.0) READ(17,'(5A)',IOSTAT=IER)	! Throw away response
+	      IF (IER.EQ.0) WRITE(17,'(2A)',IOSTAT=IER) 14,0	! Deregister
+	      CLOSE (UNIT=17)
+	   END IF
+	END IF
+
+	TEMPSET = FOLDER_SET
+	FOLDER_SET = .TRUE.
+	CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD,GROUP)
+		! in case files don't exist and are created.
+	CALL OPEN_BULLDIR			! Remove directory file
+	CALL OPEN_BULLFIL			! Remove bulletin file
+	CALL CLOSE_BULLFIL_DELETE
+	CALL CLOSE_BULLDIR_DELETE
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+	FOLDER_FILE = TEMP
+	FOLDER_SET = TEMPSET
+
+	DELETE (7)
+
+	IF (FOLDER1_NUMBER.NE.0.OR.FOLDER1_BBOARD(:2).NE.'::') THEN
+		! Test is due to bug which changes folder number to zero
+	   TEMP_NUMBER = FOLDER_NUMBER
+	   FOLDER_NUMBER = FOLDER1_NUMBER
+	   TEMP_FLAG = FOLDER_FLAG
+	   IF (BTEST(FOLDER1_FLAG,2)) THEN
+	      FOLDER_FLAG = IBCLR(FOLDER1_FLAG,2)
+	      CALL MODIFY_SYSTEM_LIST(0)
+	   END IF
+	   CALL SET_FOLDER_DEFAULT(0,0,0)
+	   FOLDER_FLAG = TEMP_FLAG
+	   FOLDER_NUMBER = TEMP_NUMBER
+	END IF
+
+	WRITE (6,'('' Folder removed.'')')
+
+	IF (FOLDER.EQ.FOLDER1) THEN
+	   CALL CLOSE_BULLFOLDER
+	   FOLDER_SET = .FALSE.
+           FOLDER_NUMBER = 0
+           CALL SELECT_FOLDER(.FALSE.,IER)
+           WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &              FOLDER(:TRIM(FOLDER))
+	   RETURN
+	ELSE
+	   REMOTE_SET = REMOTE_SET_SAVE
+	END IF
+
+1000	CALL CLOSE_BULLFOLDER
+
+	RETURN
+
+	END
+
+
+	SUBROUTINE SELECT_FOLDER(OUTPUT,IER)
+C
+C  SUBROUTINE SELECT_FOLDER
+C
+C  FUNCTION: Selects the specified folder.
+C
+C  INPUTS:
+C	OUTPUT - Specifies whether status messages are outputted.
+C
+C  NOTES:
+C	FOLDER_NUMBER is used for selecting the folder.
+C	If FOLDER_NUMBER = -1, the name stored in FOLDER1 is used.
+C	If FOLDER_NUMBER = -2, the name stored in FOLDER1 is used,
+C	but the folder is not selected if it is remote.
+C	If the specified folder is on a remote node and does not have
+C	a local entry (i.e. specified via NODENAME::FOLDERNAME), then
+C	FOLDER_NUMBER is set to -1.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($RMSDEF)'
+	INCLUDE '($SSDEF)'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	DATA REMOTE_SET /.FALSE./
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	COMMON /HEADER/ HEADER
+
+	COMMON /READIT/ READIT
+
+	COMMON /FLAG_ACCESS/ FLAG_ACCESS
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+	DATA BULL_USER_CUSTOM/.FALSE./
+
+	COMMON /LAST_FOLDER/ LAST_FOLDER_NUMBER 
+
+	EXTERNAL CLI$_ABSENT,CLI$_NEGATED
+
+	CHARACTER FSTATUS*4,FOLDER1_SAVE*44,NEWS_ACCESS*132
+
+	CHARACTER*80 LOCAL_FOLDER1_DESCRIP
+
+	DIMENSION FIRST_TIME(FLONG)	! Bit set for folder if folder has
+	DATA FIRST_TIME /FLONG*0/	! been selected before this.
+
+	DIMENSION OLD_NEWEST_BTIM(2)
+
+	DATA LAST_NEWS_GROUP/0/
+
+	CALL UPDATE_EXCLUDE
+
+	CALL UPDATE_USERINFO
+
+	COMMAND = (INCMD(:3).EQ.'ADD').OR.(INCMD(:3).EQ.'DEL').OR.
+     &		  (INCMD(:3).EQ.'DIR').OR.(INCMD(:3).EQ.'IND').OR.
+     &		  (INCMD(:3).EQ.'REP').OR.(INCMD(:3).EQ.'SEL').OR.
+     &		  (INCMD(:3).EQ.'SET').OR.(INCMD(:3).EQ.'SEA')
+
+	IF (.NOT.OUTPUT.OR.FOLDER_NUMBER.NE.-1.OR.COMMAND) THEN
+	   IF (OUTPUT) THEN			! Get folder name
+	      IER = CLI$GET_VALUE('SELECT_FOLDER',FOLDER1_NAME)
+	      FOLDER1 = FOLDER1_NAME
+	   END IF
+
+	   FLEN = TRIM(FOLDER1)		! Add GENERAL after :: if no
+	   IF (FLEN.GT.1) THEN		! name specified after the ::
+	      IF (FOLDER1(FLEN-1:FLEN).EQ.'::') THEN
+	         FOLDER1 = FOLDER1(:FLEN)//'GENERAL'
+	      END IF
+	   END IF
+
+	   IF (((IER.EQ.%LOC(CLI$_ABSENT).OR.FOLDER1.EQ.'GENERAL').AND.
+     &	    OUTPUT).OR.((FOLDER_NUMBER.EQ.0.OR.(FOLDER1.EQ.'GENERAL'.AND.
+     &	    FOLDER_NUMBER.LE.-1)).AND..NOT.OUTPUT)) THEN ! Select GENERAL
+	      FOLDER_NUMBER = 0
+	      FOLDER1 = 'GENERAL'
+	   END IF
+	END IF
+
+	REMOTE_TEST = 0
+	REMOTE_SET_NEW = 0
+
+	IF (SAVE_FOLDER_Q1.NE.0) THEN			! Have folder info
+	   FOLDER1_COM = FOLDER_COM
+	   IER = 0
+	   NEWS = INDEX(FOLDER1,'.').GT.0.OR.(FOLDER1(:1).GE.'a'.AND.
+     &					   FOLDER1(:1).LE.'z')
+	   IF (NEWS.AND.BTEST(FOLDER1_FLAG,8)) REMOTE_SET_NEW = 4
+	ELSE
+	   NEWS = ((INDEX(FOLDER1,'.').GT.0.OR.(FOLDER1(:1).GE.'a'.AND.
+     &		FOLDER1(:1).LE.'z')).AND.(FOLDER_NUMBER.LE.-1.OR.OUTPUT))
+     &		.OR.(FOLDER_NUMBER.GT.1000.AND..NOT.OUTPUT)
+	   IF (NEWS.AND.
+     &		SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) THEN
+	      CALL OPEN_BULLNEWS_SHARED		! Go find folder
+	      READ (7,IOSTAT=IER,KEYEQ=1000,KEYID=1) NEWS_FOLDER1_COM
+              NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+              NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' Fetching NEWS groups from remote node.''
+     &			,''  This will take several minutes.'')')
+		 WRITE (6,'('' This is the only time this will have''
+     &			,'' to be done.'')')
+	         CALL CLOSE_BULLFOLDER
+		 FOLDER1_SAVE = FOLDER1
+		 CALL NEWS_LIST
+	         CALL OPEN_BULLFOLDER_SHARED
+		 FOLDER1 = FOLDER1_SAVE
+	      ELSE IF (NEWS_F1_COUNT.GT.LAST_NEWS_READ(1,FOLDER_MAX).AND.
+     &		       OUTPUT.AND.NEWS_F1_COUNT.GT.LAST_NEWS_GROUP) THEN
+		 IF (LAST_NEWS_READ(1,FOLDER_MAX).GT.1000) THEN
+		    FOLDER1_SAVE = FOLDER1
+	            FOLDER1_NUMBER = LAST_NEWS_READ(1,FOLDER_MAX)
+	            IER = 2
+		    DO WHILE (IER.EQ.2)
+		       CALL READ_FOLDER_FILE_KEYNUM_GT_TEMP
+     &		          (FOLDER1_NUMBER,IER)
+		       IF (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10)) IER = 2
+	            END DO
+		    FOLDER1 = FOLDER1_SAVE
+		 END IF
+		 IF (LAST_NEWS_READ(1,FOLDER_MAX).GT.1000
+     &			.AND.IER.EQ.0) THEN
+		    WRITE (6,'('' Type NEWS/NEWGROUP to see recently'',
+     &			       '' added news groups.'')')
+		 ELSE
+		    LAST_NEWS_READ(1,FOLDER_MAX) = NEWS_F1_COUNT
+		 END IF
+		 LAST_NEWS_GROUP = NEWS_F1_COUNT
+		 FOLDER1_SAVE = FOLDER1
+	         CALL STR$UPCASE(FOLDER1,FOLDER1)
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &				(FOLDER1(:INDEX(FOLDER1,'.')),IER)
+	         IF (IER.EQ.0) THEN
+		    IF (NEWS_F1_EXPIRE.GT.0) 
+     &		       NEWS_EXPIRE_DEFAULT = NEWS_F1_EXPIRE
+		    IF (NEWS_F1_EXPIRE_LIMIT.NE.0) 
+     &		       NEWS_EXPIRE_LIMIT_DEFAULT = NEWS_F1_EXPIRE_LIMIT
+	         END IF
+	         FOLDER1 = FOLDER1_SAVE
+	      END IF
+	      CALL LOWERCASE(FOLDER1)
+	   ELSE
+	      CALL OPEN_BULLFOLDER_SHARED		! Go find folder
+	   END IF
+
+	   IF ((OUTPUT.AND.(FOLDER_NUMBER.NE.0.OR.FOLDER1.NE.'GENERAL'))
+     &		.OR.FOLDER_NUMBER.LE.-1) THEN
+	      REMOTE_TEST = INDEX(FOLDER1,'::')
+	      IF (REMOTE_TEST.GT.0) THEN
+	         FOLDER1_BBOARD = '::'//FOLDER1(:REMOTE_TEST-1)
+	         FOLDER1 = FOLDER1(REMOTE_TEST+2:TRIM(FOLDER1))
+	         FOLDER1_NUMBER = -1
+	         IER = 0
+	      ELSE IF (INCMD(:2).EQ.'SE') THEN
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &				(FOLDER1(:TRIM(FOLDER1)),IER)
+	      ELSE
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	      END IF
+	   ELSE
+	      FOLDER1_NUMBER = FOLDER_NUMBER
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(FOLDER_NUMBER,IER)
+	   END IF
+
+	   IF (REMOTE_TEST.EQ.0.AND.IER.EQ.0) THEN
+	      IF (BTEST(FOLDER1_FLAG,29)) THEN		! Error in folder flag!!
+	         FOLDER1_FLAG = FOLDER1_FLAG.AND.3
+	         F1_EXPIRE_LIMIT = 0
+	         CALL REWRITE_FOLDER_FILE_TEMP(IER1)
+	      END IF
+	   END IF
+
+	   CALL CLOSE_BULLFOLDER
+
+	   IF (NEWS.AND.BTEST(FOLDER1_FLAG,8).AND.IER.EQ.0) THEN
+	      REMOTE_SET_NEW = 4
+	      CALL SYS_BINTIM('-',EX_BTIM)
+	   END IF
+	END IF
+
+	IF (BTEST(FOLDER1_FLAG,9)) THEN
+	   IF (OUTPUT) THEN
+	       WRITE(6,'('' This news group has been disabled.'')')
+	   END IF
+	   IER = 2
+	   RETURN
+	END IF
+
+	IF ((IER.EQ.0.OR.NEWS).AND.REMOTE_SET_NEW.NE.4.AND.
+     &		FOLDER1_BBOARD(:2).EQ.'::') THEN
+	   IF (FOLDER_NUMBER.EQ.-2) RETURN	! Don't allow
+	   IF (IER.NE.0) FOLDER1_DESCRIP = FOLDER1_NAME
+	   LOCAL_FOLDER1_FLAG = FOLDER1_FLAG
+	   LOCAL_FOLDER1_DESCRIP = FOLDER1_DESCRIP
+	   CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER1)
+	   IF (IER1.NE.0) THEN
+	      IF (OUTPUT) THEN
+	         WRITE (6,'('' ERROR: Unable to select the folder.'')')
+		 IF (.NOT.NEWS) THEN
+		    LENB = TRIM(FOLDER1_BBOARD)
+		    IF (FOLDER1_BBOARD(LENB:LENB).EQ.'*') LENB = LENB - 1
+	            WRITE (6,'('' Cannot connect to node '',A,''.'')')
+     &		        FOLDER1_BBOARD(3:LENB)
+		 ELSE IF (.NOT.IER1) THEN
+	            WRITE (6,'('' Cannot connect to remote NEWS node.'')')
+	         END IF
+	      END IF
+	      RETURN
+	   END IF
+	   IF (REMOTE_TEST.GT.0) THEN	! Folder specified with "::"
+	      FOLDER1 = FOLDER1_BBOARD(3:TRIM(FOLDER1_BBOARD))//'::'//
+     &			FOLDER1
+	      FOLDER1_NUMBER = -1
+	      REMOTE_SET_NEW = 1
+	   ELSE IF (NEWS) THEN
+	      REMOTE_SET_NEW = 3
+	      CALL OPEN_BULLNEWS_SHARED	! Update local folder information
+	      IF (IER.NE.0) CALL NEWS_NEW_FOLDER
+              CALL READ_FOLDER_FILE_KEYNAME(FOLDER1,IER)
+	      IF ((F1_START.NE.F_START.OR.F1_NBULL.NE.F_NBULL).AND.
+     &		  (F1_START.GT.0.OR.F_START.LE.F_NBULL)) THEN
+	         IF (F1_NBULL.NE.F_NBULL) CALL SYS_BINTIM('-',F_NEWEST_BTIM)
+	         F_COUNT = F1_COUNT
+		 IF (F1_START.GT.0) THEN
+		    IF (F1_NBULL.LT.F_NBULL) THEN
+		       CALL NEWS_GET_NEWEST_MESSAGE(IER)
+		       IF (IER-1.GE.F1_NBULL) THEN 
+			  CALL NEWS_UPDATE_NEWEST_MESSAGE(F_NBULL)
+		       END IF
+		    ELSE
+	               F_NBULL = F1_NBULL
+		    END IF
+	            F_START = F1_START
+		 ELSE
+		    F_START = F_NBULL + 1
+		 END IF
+	         CALL REWRITE_FOLDER_FILE(IER)
+	      END IF
+	      CALL CLOSE_BULLFOLDER
+	   ELSE				! True remote folder
+	      FOLDER1_DESCRIP = LOCAL_FOLDER1_DESCRIP	! Use local description
+	      IF (BTEST(FOLDER1_FLAG,0)) THEN	! If remote folder is protected
+		 LOCAL_FOLDER1_FLAG = IBSET(LOCAL_FOLDER1_FLAG,0)
+	      END IF
+	      FOLDER1_FLAG = LOCAL_FOLDER1_FLAG		! Use local flag info
+	      REMOTE_SET_NEW = 1
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN				! Folder found
+	   FLAG1_ACCESS = .TRUE.
+	   CALL SET_FOLDER_FILE(1)
+	   IF (BTEST(FOLDER1_FLAG,0)) THEN		! Folder protected?
+	      IF (NEWS) THEN
+		 CALL CHKACL(NEWS_ACCESS(FOLDER1_DESCRIP),IER)
+	      ELSE
+	         CALL CHKACL
+     &		 (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',IER)
+	      END IF
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.USERNAME
+     &		  .NE.FOLDER1_OWNER.AND.IER) THEN
+	         IF (NEWS) THEN
+	            CALL CHECK_ACCESS
+     &		     (NEWS_ACCESS(FOLDER1_DESCRIP),
+     &		     USERNAME,READ_ACCESS,WRITE_ACCESS)
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		     USERNAME,READ_ACCESS,WRITE_ACCESS)
+	         END IF
+	         IF (SETPRV_PRIV().AND.READIT.EQ.0) THEN
+		    IF (.NOT.READ_ACCESS) FLAG1_ACCESS = .FALSE.
+	            READ_ACCESS = 1
+		    WRITE_ACCESS = 1
+	         END IF
+	         IF (.NOT.READ_ACCESS.AND..NOT.WRITE_ACCESS) THEN
+		  IF (OUTPUT.AND.NEWS) THEN
+	           WRITE(6,'('' You are not allowed to access news group.'')')
+		  ELSE IF (NEWS) THEN
+		   IF (NEWS_FIND_SUBSCRIBE().LE.FOLDER_MAX-1) THEN
+		      CALL NEWS_SET_USER_FLAG(0,0,0)
+		   END IF
+		  ELSE IF (OUTPUT) THEN
+	           WRITE(6,'('' You are not allowed to access folder.'')')
+	           WRITE(6,'('' See '',A,'' if you wish to access folder.'')')
+     &			FOLDER1_OWNER(:TRIM(FOLDER1_OWNER))
+		  ELSE IF (TEST2(BRIEF_FLAG,FOLDER1_NUMBER).OR.
+     &			 TEST2(SET_FLAG,FOLDER1_NUMBER)) THEN
+		   CALL OPEN_BULLUSER_SHARED
+		   CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+		   CALL CLR2(BRIEF_FLAG,FOLDER1_NUMBER)
+		   CALL CLR2(SET_FLAG,FOLDER1_NUMBER)
+		   IF (IER.EQ.0) REWRITE (4) USER_ENTRY
+		   CALL CLOSE_BULLUSER
+		  END IF
+		  IER = 0
+		  RETURN
+	         END IF
+	      ELSE IF (BTEST(FOLDER1_FLAG,0).AND.(.NOT.IER.OR.
+     &		  (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND..NOT.NEWS))
+     &		  .AND.(FOLDER1_BBOARD(:2).NE.'::'.OR.NEWS)) THEN
+	         IF (NEWS) THEN
+	            CALL OPEN_BULLNEWS_SHARED
+	         ELSE
+	            CALL OPEN_BULLFOLDER
+	         END IF
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER1)
+		 FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+	         CALL REWRITE_FOLDER_FILE_TEMP(IER1) 
+		 CALL CLOSE_BULLFOLDER
+	      ELSE IF (FOLDER1_BBOARD(:2).EQ.'::') THEN
+	         IER = SS$_ACLEMPTY.OR.SS$_NORMAL
+	      END IF
+	   ELSE					! Folder not protected
+	      IER = SS$_ACLEMPTY.OR.SS$_NORMAL	! Indicate folder selected
+	   END IF
+
+	   IF (REMOTE_SET_NEW.NE.1.AND.REMOTE_SET.EQ.1) 
+     &					CLOSE(UNIT=REMOTE_UNIT)
+
+	   REMOTE_SET = REMOTE_SET_NEW 
+
+	   IF (IER) THEN
+	      FLAG_ACCESS = FLAG1_ACCESS	! Can set flags?
+
+	      FOLDER_COM = FOLDER1_COM		! Folder successfully set so
+	      FOLDER_FILE = FOLDER1_FILE	! update folder parameters
+
+	      IF (FOLDER_NUMBER.NE.0) THEN
+		 FOLDER_SET = .TRUE.
+	      ELSE
+		 FOLDER_SET = .FALSE.
+	      END IF
+
+	      IF (REMOTE_SET.LT.3) THEN
+		 FOLDER_NAME = FOLDER
+	         HEADER = .NOT.BTEST(FOLDER_FLAG,4)
+	      ELSE
+		 IF (COMMAND.AND.INCMD(:3).NE.'REP'.AND.
+     &		     INCMD(:3).NE.'DEL') HEADER = .FALSE.
+		 FOLDER_NAME = FOLDER_DESCRIP(:INDEX(FOLDER_DESCRIP,' ')-1)
+	         IF (REMOTE_SET.EQ.4) NEWS_FOLDER_COM = NEWS_FOLDER1_COM
+	      END IF
+
+	      IF (REMOTE_SET.EQ.1.AND.FOLDER_NUMBER.GE.0) THEN
+	         CALL OPEN_BULLFOLDER	! Update local folder information
+                 CALL READ_FOLDER_FILE_KEYNAME(FOLDER1,IER1)
+	         OLD_NEWEST_BTIM(1) = F_NEWEST_BTIM(1)
+      	         OLD_NEWEST_BTIM(2) = F_NEWEST_BTIM(2)
+	         FOLDER_COM = FOLDER1_COM
+	         CALL REWRITE_FOLDER_FILE(IER1)
+	         CALL CLOSE_BULLFOLDER
+	         DIFF = COMPARE_BTIM(OLD_NEWEST_BTIM,F_NEWEST_BTIM)
+	         IF (DIFF.LT.0.AND.IER1.EQ.0) THEN
+	            CALL READ_NOTIFY
+	            IF (TEST2(NOTIFY_REMOTE,FOLDER_NUMBER)) THEN
+		       CALL NOTIFY_REMOTE_USERS(OLD_NEWEST_BTIM)
+	            END IF
+	         END IF
+	      END IF
+
+	      IF (REMOTE_SET.EQ.0.AND..NOT.BTEST(FOLDER_FLAG,10)
+     &		   .AND..NOT.BTEST(FOLDER_FLAG,11).AND.WRITE_ACCESS) THEN
+	         SLIST = INDEX(FOLDER_DESCRIP,'<')
+                 IF (OUTPUT.AND.INCMD(:3).NE.'DIR') THEN
+                    IF (NEWS_FEED()) THEN
+                       WRITE (6,'('' Use the POST command to send a '',
+     &                 ''message to this folder''''s news group.'')')
+		    ELSE IF (SLIST.GT.0) THEN
+                       WRITE (6,'('' Use the POST command to send a '',
+     &                 ''message to this folder''''s mailing list.'')')
+                    END IF
+                 END IF
+	      END IF
+
+	      IF (OUTPUT.AND.INCMD(:3).NE.'DIR') THEN
+		 WRITE (6,'('' Folder has been set to '',A)') 
+     &		    FOLDER_NAME(:TRIM(FOLDER_NAME))//'.'
+	      END IF
+
+	      IF (OUTPUT) THEN
+		 IF (REMOTE_SET.EQ.3) THEN
+		    BULL_POINT = F_START - 1
+		    FSTATUS(:1) = 
+     &			FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,' ')+1:)
+		    IF (STREQ(FSTATUS(:1),'X')) THEN
+		       WRITE (6,'('' WARNING: The local news server has'',
+     &				  '' deactivated this group.'')')
+		    ELSE IF (STREQ(FSTATUS(:1),'=')) THEN
+		       WRITE (6,'('' NOTE: This group is no longer'',
+     &				  '' active.  It has been replaced by:'')')
+		       WRITE (6,'(1X,A)') FOLDER_DESCRIP(
+     &				       INDEX(FOLDER_DESCRIP,'=')+1:)
+		    END IF
+		 ELSE IF (REMOTE_SET.EQ.4) THEN
+		    BULL_POINT = F_START - 1 
+		 ELSE
+		    BULL_POINT = 0	! Reset pointer to first bulletin
+	         END IF
+	      ELSE IF (REMOTE_SET.EQ.3.OR.REMOTE_SET.EQ.4) THEN
+		 BULL_POINT = F_START - 1
+	      END IF
+
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.USERNAME
+     &		  .NE.FOLDER_OWNER) THEN
+	         IF (.NOT.WRITE_ACCESS) THEN
+		   IF (OUTPUT.AND.INCMD(:3).NE.'DIR'.AND.SLIST.EQ.0) THEN
+		    WRITE (6,'('' Folder only accessible for reading.'')')
+		   END IF
+		   READ_ONLY = .TRUE.
+		 ELSE
+		   READ_ONLY = .FALSE.
+		 END IF
+	      ELSE
+		 READ_ONLY = .FALSE.
+	      END IF
+
+	      IF (FOLDER_NUMBER.GT.0.AND.REMOTE_SET.LT.3) THEN
+		IF (TEST_BULLCP().GT.0.OR.REMOTE_SET) THEN
+		 CALL SET2(FIRST_TIME,FOLDER_NUMBER)
+		ELSE IF (.NOT.TEST2(FIRST_TIME,FOLDER_NUMBER)) THEN
+	       			! If first select, look for expired messages.
+		 CALL OPEN_BULLDIR
+		 CALL READDIR(0,IER)	! Get header info from BULLDIR.DAT
+	 	 IF (IER.EQ.1) THEN		! Is header present?
+	   	    IER = COMPARE_DATE(NEWEST_EXDATE,' ') ! Yes. Any expired?
+		    IF (SHUTDOWN.GT.0.AND.NODE_AREA.GT.0.AND.
+     &			(FOLDER_NUMBER.EQ.0.OR.BTEST(FOLDER_FLAG,2))
+     &			.AND.TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+						! Do shutdown bulletins exist?
+		       SHUTDOWN = 0
+		       IER1 = -1
+		    ELSE
+		       IF (TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+			  CALL UPDATE_SHUTDOWN(FOLDER_NUMBER)
+		       END IF
+	               IER1 = 1
+		    END IF
+	 	    IF (IER.LE.0.OR.IER.GT.20*356.OR.IER1.LE.0) THEN
+		       CALL UPDATE	! Need to update
+		    END IF
+		 ELSE
+		    NBULL = 0
+		 END IF
+		 CALL CLOSE_BULLDIR
+		 CALL SET2(FIRST_TIME,FOLDER_NUMBER)
+	        END IF
+	      END IF
+
+	      IF (OUTPUT) THEN
+		 IF (CLI$PRESENT('MARKED')) THEN
+		    READ_TAG = 1 + IBSET(0,1)
+		    BULL_PARAMETER = 'MARKED'
+		 ELSE IF (CLI$PRESENT('SEEN')) THEN
+		    READ_TAG = 1 + IBSET(0,2)
+		    BULL_PARAMETER = 'SEEN'
+	         ELSE IF (CLI$PRESENT('UNMARKED').OR.CLI$PRESENT
+     &		       ('MARKED').EQ.%LOC(CLI$_NEGATED)) THEN
+		    READ_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+		    BULL_PARAMETER = 'UNMARKED'
+	         ELSE IF (CLI$PRESENT('UNSEEN').OR.CLI$PRESENT
+     &		       ('SEEN').EQ.%LOC(CLI$_NEGATED)) THEN
+		    READ_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+		    BULL_PARAMETER = 'UNSEEN'
+		 ELSE
+		    READ_TAG = IBSET(0,1) + IBSET(0,2)
+		 END IF
+	         IF (READ_TAG) THEN
+	            IF (FOLDER_NUMBER.GE.0) THEN
+		       CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,BULL_POINT)
+		    ELSE
+		       WRITE (6,'('' ERROR: invalid qualifier'',
+     &			          '' with remote folder.'')')
+		       READ_TAG = IBSET(0,1) + IBSET(0,2)
+		    END IF
+	         END IF
+	         IF (READ_TAG.AND.INCMD(:3).NE.'DIR') THEN
+		    IF (IER.EQ.0) THEN
+		       WRITE(6,'('' NOTE: Only '',A,'' messages'',
+     &			   '' will be shown.'')')
+     &			   BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+		    ELSE
+		       WRITE(6,'('' WARNING: No '',A,
+     &			   '' messages found.'')')
+     &		 	   BULL_PARAMETER(:TRIM(BULL_PARAMETER))
+		    END IF
+	         END IF
+	      END IF
+
+	      IF (REMOTE_SET.GE.3.AND.OUTPUT.AND..NOT.READ_TAG) THEN
+		 CALL NEWS_GET_NEWEST_MESSAGE(IER)
+		 IF (IER.GT.0.AND.IER.LE.F_NBULL) THEN
+		    BULL_POINT = IER - 1
+	            WRITE(6,'('' Type READ to read new messages.'')')
+		 END IF
+	      ELSE IF (FOLDER_NUMBER.NE.0.AND..NOT.READ_TAG.AND.
+     &		  				REMOTE_SET.LT.3) THEN
+	        IF (OUTPUT.AND.INCMD(:3).NE.'DIR') THEN
+	         DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+	         IF (DIFF.LT.0.AND.F_NBULL.GT.0) THEN 	! If new unread messages
+		  CALL FIND_NEWEST_BULL			! See if we can find it
+		  IF (BULL_POINT.NE.-1) THEN
+	     	    WRITE(6,'('' Type READ to read new messages.'')')
+		    NEW_COUNT = F_NBULL - BULL_POINT
+		    DIG = 0
+		    DO WHILE (NEW_COUNT.GT.0)
+		      NEW_COUNT = NEW_COUNT / 10
+		      DIG = DIG + 1
+		    END DO
+		    WRITE(6,'('' There are '',I<DIG>,'' new messages.'')')
+     &			F_NBULL - BULL_POINT	! Alert user if new bulletins
+		  ELSE
+		    CALL COPY2(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &			       F_NEWEST_BTIM)
+		    BULL_POINT = 0
+		  END IF
+		 END IF
+		END IF
+	      END IF
+	      IER = 1
+	      IF (TEST_BULLCP().NE.2) CALL CHECK_CUSTOM
+	      IF (BTEST(BULL_USER_CUSTOM,2)) HEADER = .TRUE.
+	   ELSE IF (OUTPUT) THEN
+	      WRITE (6,'('' Cannot access specified folder.'')')
+	      CALL SYS_GETMSG(IER)
+	   END IF
+	ELSE						! Folder not found
+	   IF (OUTPUT) WRITE (6,'('' ERROR: Folder does not exist.'')')
+	   IER = 0
+	END IF
+
+	LAST_FOLDER_NUMBER = FOLDER_NUMBER 
+
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE UPDATE_FOLDER
+C
+C  SUBROUTINE UPDATE_FOLDER
+C
+C  FUNCTION: Updates folder info due to new message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	IF (FOLDER_NUMBER.LT.0) RETURN
+
+	CALL OPEN_BULLFOLDER_SHARED			! Open folder file
+
+	CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,F_NEWEST_BTIM)
+
+	F_NBULL = NBULL
+
+	IF (FOLDER_NUMBER.EQ.0) FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+
+	IF (.NOT.BTEST(SYSTEM,0)) THEN 	! Is non-system message?
+	   F_NEWEST_NOSYS_BTIM(1) = F_NEWEST_BTIM(1) ! If so, update latest
+	   F_NEWEST_NOSYS_BTIM(2) = F_NEWEST_BTIM(2) ! system time.
+	END IF
+
+	CALL REWRITE_FOLDER_FILE(IER)
+
+	CALL CLOSE_BULLFOLDER
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SHOW_FOLDER
+C
+C  SUBROUTINE SHOW_FOLDER
+C
+C  FUNCTION: Shows the information on any folder.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /BULL_PERM/ SET_PERM_FLAG,BRIEF_PERM_FLAG,NOTIFY_PERM_FLAG
+	DIMENSION SET_PERM_FLAG(FLONG)
+	DIMENSION BRIEF_PERM_FLAG(FLONG)
+	DIMENSION NOTIFY_PERM_FLAG(FLONG)
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	EXTERNAL CLI$_ABSENT,BULLETIN_SUBCOMMANDS
+
+	IF (INDEX(INCMD,'/A').GT.0.OR.INDEX(INCMD,'/a').GT.0) THEN
+	   WRITE (6,'('' ERROR: /ALL is invalid qualifier.'')')
+	   RETURN
+	END IF
+
+	IF (CLI$GET_VALUE('SHOW_FOLDER',FOLDER1).EQ.%LOC(CLI$_ABSENT))
+     &	   THEN
+	   FOLDER1 = FOLDER
+	   IF (INDEX(FOLDER1,'.').GT.0) CALL LOWERCASE(FOLDER1)
+	END IF
+
+	IF (INDEX(FOLDER1,'::').NE.0) THEN
+ 	   WRITE (6,'('' ERROR: invalid command for remote folder.'')')
+	   RETURN
+	END IF
+
+	IF (TEST_NEWS(FOLDER1)) THEN              
+	   INCMD = 'SET NEWS '
+	   IF (CLI$PRESENT('FULL')) INCMD = 'SET NEWS/FULL '
+	   IF (CLI$PRESENT('SHOW_FOLDER')) INCMD = 'SET NEWS '//FOLDER1
+           CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	   CALL SHOW_NEWS
+	   RETURN
+        END IF
+
+	CALL OPEN_BULLFOLDER_SHARED
+
+	CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: Specified folder was not found.'')')
+	   CALL CLOSE_BULLFOLDER
+	   RETURN
+	ELSE IF (FOLDER.EQ.FOLDER1) THEN
+	   WRITE (6,1000) FOLDER1,FOLDER1_OWNER,
+     &			FOLDER1_DESCRIP(:TRIM(FOLDER1_DESCRIP))
+	ELSE
+	   WRITE (6,1010) FOLDER1,FOLDER1_OWNER,
+     &			FOLDER1_DESCRIP(:TRIM(FOLDER1_DESCRIP))
+	END IF
+
+	IF (CLI$PRESENT('FULL')) THEN
+	   CALL SET_FOLDER_FILE(1)
+	   CALL CHKACL
+     &		 (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',IER)
+	   IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL).OR.(.NOT.IER)) THEN
+	      IF (FOLDER1_BBOARD(:2).EQ.'::'.AND.	! Is folder remote
+     &		BTEST(FOLDER1_FLAG,0)) THEN		! and private?
+	         WRITE (6,'('' Access is limited.'')')
+	      END IF
+	   ELSE
+	      IF (SETPRV_PRIV()) THEN
+	         READ_ACCESS = 1
+		 WRITE_ACCESS = 1
+	      ELSE
+	        CALL CHECK_ACCESS
+     &		  (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		   USERNAME,READ_ACCESS,WRITE_ACCESS)
+	      END IF
+	      IF (WRITE_ACCESS)
+     &	      CALL SHOWACL(FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL')
+	   END IF
+	   IF (FOLDER_ACCESS(USERNAME,FOLDER1_FLAG,FOLDER1_OWNER)) THEN
+	      IF (FOLDER1_BBOARD(:2).EQ.'::') THEN
+		 FLEN = TRIM(FOLDER1_BBOARD)
+		 IF (INDEX(FOLDER1_BBOARD,'*').EQ.0) THEN
+		    WRITE (6,'('' Folder is located on node '',
+     &		     A,''.'')') FOLDER1_BBOARD(3:FLEN)
+		 ELSE
+		    CALL SET_FOLDER_FILE(1)
+		    FOLDER_FILE = FOLDER1_FILE
+		    REMOTE_SET_SAVE = REMOTE_SET
+		    REMOTE_SET = .FALSE.
+		    CALL OPEN_BULLDIR
+		    CALL READDIR(0,IER)
+		    CALL CLOSE_BULLDIR
+		    CALL SET_FOLDER_FILE(0)
+		    REMOTE_SET = REMOTE_SET_SAVE
+		    WRITE (6,'('' Folder is located on node '',
+     &		       A,''. Remote folder name is '',A,''.'')') 
+     &		       FOLDER1_BBOARD(3:FLEN-1),
+     &		       BULLDIR_HEADER(13:TRIM(BULLDIR_HEADER))
+		 END IF
+	      ELSE IF (FOLDER1_BBOARD(:4).NE.'NONE') THEN
+		 FLEN = TRIM(FOLDER1_BBOARD)
+		 IF (FLEN.GT.0) THEN
+ 	          WRITE (6,'('' BBOARD for folder is '',A<FLEN>,''.'')')
+     &		 	FOLDER1_BBOARD(:FLEN)
+		 END IF
+		 IF ((USERB1.EQ.0.AND.GROUPB1.EQ.0).OR.BTEST(USERB1,31)) THEN
+ 		  WRITE (6,'('' BBOARD was specified with /SPECIAL.'')')
+		  IF (BTEST(GROUPB1,31)) THEN
+		   WRITE (6,'('' BBOARD was specified with /VMSMAIL.'')')
+		  END IF
+		 END IF
+	      ELSE
+	         WRITE (6,'('' No BBOARD has been defined.'')')
+	      END IF
+	      IF (FOLDER1_BBEXPIRE.GT.0) THEN
+		 WRITE (6,'('' Default expiration is '',I3,'' days.'')')
+     &			FOLDER1_BBEXPIRE
+	      ELSE IF (FOLDER1_BBEXPIRE.EQ.-1) THEN
+		 WRITE (6,'('' Default expiration is permanent.'')')
+	      ELSE
+		 WRITE (6,'('' No default expiration set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,2)) THEN
+		 WRITE (6,'('' SYSTEM has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,1)) THEN
+		 WRITE (6,'('' DUMP has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,3)) THEN
+		 WRITE (6,'('' NOPROMPT_EXPIRE has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,4)) THEN
+		 WRITE (6,'('' STRIP has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,5)) THEN
+		 WRITE (6,'('' DIGEST has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,7)) THEN
+		 WRITE (6,'('' ALWAYS has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,10)) THEN
+		 WRITE (6,'('' POST_ONLY has been set.'')')
+	      ELSE IF (BTEST(FOLDER1_FLAG,11)) THEN
+		 WRITE (6,'('' ADD_ONLY has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,12)) THEN
+		 WRITE (6,'('' COMPRESS has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,14)) THEN
+		 WRITE (6,'('' ANONYMOUS has been set.'')')
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,15)) THEN
+		 WRITE (6,'('' GATEWAY has been set.'')')
+	      END IF
+	      IF (F1_EXPIRE_LIMIT.GT.0) THEN
+		 WRITE (6,'('' EXPIRATION limit is '',I3,'' days.'')')
+     &			F1_EXPIRE_LIMIT
+	      END IF
+	      CALL OPEN_BULLUSER_SHARED
+	      CALL READ_USER_FILE_HEADER(IER)
+	      CALL READ_PERM
+	      PERM = .FALSE.
+	      IF (TEST2(SET_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	       IF (TEST2(BRIEF_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	        IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is BRIEF, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is BRIEF.'')')
+		END IF
+	       ELSE
+	        IF (TEST2(SET_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER)) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is READNEW, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is READNEW.'')')
+		END IF
+	       END IF
+	      ELSE
+	       IF (TEST2(BRIEF_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	        IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+	         PERM = .TRUE.
+		 WRITE (6,'('' Default is SHOWNEW, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is SHOWNEW.'')')
+		END IF
+	       END IF
+	      END IF
+	      IF (.NOT.PERM) THEN
+	        IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		   WRITE (6,'('' BRIEF is the permanent setting.'')')
+	        ELSE IF (TEST2(SET_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		   WRITE (6,'('' READNEW is the permanent setting.'')')
+	        ELSE IF (TEST2(BRIEF_PERM_FLAG,FOLDER1_NUMBER).AND.
+     &		    .NOT.TEST2(SET_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		   WRITE (6,'('' SHOWNEW is the permanent setting.'')')
+	        END IF
+	      END IF
+	      IF (TEST2(NOTIFY_FLAG_DEF,FOLDER1_NUMBER)) THEN
+	        IF (TEST2(NOTIFY_PERM_FLAG,FOLDER1_NUMBER)) THEN
+		 WRITE (6,'('' Default is NOTIFY, which is permanent.'')')
+		ELSE
+		 WRITE (6,'('' Default is NOTIFY.'')')
+		END IF
+	      ELSE
+		 WRITE (6,'('' Default is NONOTIFY.'')')
+	      END IF
+	      CALL CLOSE_BULLUSER
+	   END IF
+	   IF (NEWS_FEED()) THEN
+	      WRITE (6,'('' Last message fed by news group was: '',I)') F_LAST
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLFOLDER
+
+	RETURN
+
+1000	FORMAT(' Current folder: ',A44,' Owner: ',A12,/,
+     &		' Description: ',A)
+1010	FORMAT(' Folder name is: ',A44,' Owner: ',A12,/,
+     &		' Description: ',A)
+	END
+
+
+	SUBROUTINE DIRECTORY_FOLDERS(FOLDER_COUNT)
+C
+C  SUBROUTINE DIRECTORY_FOLDERS
+C
+C  FUNCTION: Display all FOLDER entries.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	DATA SCRATCH_D1/0/
+
+	CHARACTER FOLDER_MATCH*80,DATETIME*20,FSTATUS1*4,NEWS_ACCESS*132 
+
+	INTEGER*2 MLEN,FLEN
+
+	OLD_BUFFER = ' '
+
+	IF (CLI$PRESENT('NEWS')) THEN
+	   IF (SYS_TRNLNM('BULL_NEWS_SERVER','DEFINED')) THEN
+	      CALL OPEN_BULLNEWS_SHARED
+	   ELSE
+	      WRITE (6,'('' ERROR: NEWS connection is not present.'')')
+	      RETURN
+	   END IF
+	ELSE
+	   CALL OPEN_BULLFOLDER_SHARED		! Get folder file
+	END IF
+
+	IF (FOLDER_COUNT.EQ.0) THEN
+	   SUBSCRIBE = .FALSE.
+	   ACTIVE = .FALSE. 
+	   STORED = .FALSE. 
+	   CLASS = .FALSE.
+	   NEW = .FALSE.
+	   PERM = .FALSE.
+	   DEFA = .FALSE.
+	   FOLDER_COUNT = 1			! Init folder number counter
+	   NLINE = 1
+	   START = .FALSE.
+	   IF (.NOT.CLI$PRESENT('NEWS')) THEN
+	      NEWS = .FALSE.
+	      IF (CLI$PRESENT('DESCRIBE')) THEN
+	         NLINE = 2	! Include folder descriptor if /DESCRIBE
+	      END IF
+	   ELSE
+	      NEWS = .TRUE.
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP('a',IER)
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' Fetching NEWS groups from remote node.''
+     &			,''  This will take several minutes.'')')
+		 WRITE (6,'('' This is the only time this will have''
+     &			,'' to be done.'')')
+	         CALL CLOSE_BULLFOLDER
+		 CALL NEWS_LIST
+	         CALL OPEN_BULLNEWS_SHARED
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP('a',IER)
+	      END IF
+	      COUNT = CLI$PRESENT('COUNT')
+	      IF (COUNT) TOTAL_COUNT = 0
+	      STORED = CLI$PRESENT('STORED')
+	      SUBSCRIBE = CLI$PRESENT('SUBSCRIBE')
+	      NEW = CLI$PRESENT('NEWGROUPS')
+	      CLASS = CLI$PRESENT('CLASS')
+	      PERM = CLI$PRESENT('PERMANENT')
+	      DEFA =  CLI$PRESENT('DEFAULT')
+	      IF (CLASS) THEN
+	         CALL CLOSE_BULLFOLDER
+	         CALL OPEN_BULLNEWS_SHARED
+	      END IF
+	      IF (NEW) THEN
+		 NEW_NEWS = MAX(LAST_NEWS_READ(1,FOLDER_MAX),1000)
+	      ELSE IF (SUBSCRIBE) THEN
+		 CALL NEWS_GET_SUBSCRIBE(0,F1_COUNT)
+		 SUBNUM = 1
+	      ELSE IF (PERM) THEN
+	      	 CALL OPEN_BULLINF_SHARED
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,KEY='*PERM',IOSTAT=IER) TEMP_USER,INF_REC
+		 END DO
+		 IF (IER.NE.0) THEN
+	            DO I=1,FOLDER_MAX
+	               INF_REC(1,I) = 0
+	               INF_REC(2,I) = 0
+	            END DO
+	         END IF
+		 CALL CLOSE_BULLINF
+		 INUM = 1
+	      ELSE IF (DEFA) THEN
+	      	 CALL OPEN_BULLINF_SHARED
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,KEY='*DEFAULT',IOSTAT=IER) TEMP_USER,INF_REC
+		 END DO
+		 IF (IER.NE.0) THEN
+	            DO I=1,FOLDER_MAX
+	               INF_REC(1,I) = 0
+	               INF_REC(2,I) = 0
+	            END DO
+	         END IF
+		 CALL CLOSE_BULLINF
+		 INUM = 1
+	      ELSE
+	         ACTIVE = .NOT.CLI$PRESENT('ALL')
+	      END IF
+	   END IF
+	   IF (CLI$GET_VALUE('START',FOLDER1,FLEN)) THEN
+	      IF (NEWS) CALL LOWERCASE(FOLDER1)
+	      CALL READ_FOLDER_FILE_KEYNAMEGE_TEMP(FOLDER1(:FLEN),IER)
+	      IF (IER.NE.0) THEN
+		 WRITE (6,'('' There are no folders.'')')
+	         CALL CLOSE_BULLFOLDER
+		 FOLDER_COUNT = -1
+		 RETURN
+	      ELSE
+		 START = .TRUE.
+	      END IF
+	   END IF
+	   MATCH = CLI$GET_VALUE('MATCH_FOLDER',FOLDER_MATCH,MLEN)
+	   IF (MATCH.AND.NEWS) CALL LOWERCASE(FOLDER_MATCH)
+	   IF (MATCH.AND.INDEX(FOLDER_MATCH,'*').EQ.0) THEN
+	      FOLDER_MATCH = '*'//FOLDER_MATCH(:MLEN)//'*'
+	      MLEN = MLEN + 2
+	   END IF
+	ELSE IF (NEWS.AND.COUNT.AND.TOTAL_COUNT.LT.0) THEN
+	   WRITE (6,'('' The total count is: '',I)') -TOTAL_COUNT
+	   TOTAL_COUNT = 0
+	   FOLDER_COUNT = -1
+	   RETURN
+	ELSE IF (SUBSCRIBE.AND.PAGING.AND.MORE) THEN
+	   SUBNUM = -2
+	ELSE
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	END IF
+
+C
+C  Folder listing is first buffered into temporary memory storage before
+C  being outputted to the terminal.  This is to be able to quickly close the
+C  folder file, and to avoid the possibility of the user holding the screen,
+C  and thus causing the folder file to stay open.  The temporary memory
+C  is structured as a linked-list queue, where SCRATCH_D1 points to the header
+C  of the queue.
+C
+	CALL INIT_QUEUE(SCRATCH_D1,FOLDER1_COM)
+	SCRATCH_D = SCRATCH_D1
+
+	CALL DECLARE_CTRLC_AST
+
+	NUM_FOLDER = 0
+	IER = 0
+	IER1 = 0
+	MORE = .FALSE.
+	NEWS_TEST = MATCH.OR.ACTIVE.OR.STORED
+	DO WHILE (IER.EQ.0.AND.IER1.EQ.0)
+	   IF (SUBSCRIBE) THEN
+	      IER = 1
+	      DO WHILE (SUBNUM.NE.0.AND.IER.NE.0)
+	         CALL NEWS_GET_SUBSCRIBE(SUBNUM,MSGNUM)
+		 IF (SUBNUM.NE.0) THEN
+	            CALL READ_FOLDER_FILE_KEYNUM_TEMP(SUBNUM,IER)
+		    IF (IER.NE.0) SUBNUM = -1
+		 END IF
+	      END DO
+	      IF (SUBNUM.EQ.0) IER = 1
+	   ELSE IF (PERM.OR.DEFA) THEN
+	      IER = 1
+	      DO WHILE (INUM.LE.FOLDER_MAX.AND.IER.NE.0)
+		 IF (INF_REC2(1,INUM).NE.0) THEN
+	            CALL READ_FOLDER_FILE_KEYNUM_TEMP
+     &				(ZEXT(INF_REC2(1,INUM)),IER)
+		 END IF
+		 INUM = INUM + 1
+	      END DO
+	   ELSE IF (START) THEN
+	      START = .FALSE.
+	   ELSE IF (NEW) THEN
+	      IER = 2
+	      DO WHILE (IER.EQ.2)
+	         CALL READ_FOLDER_FILE_KEYNUM_GT_TEMP(NEW_NEWS,IER)
+		 IF (IER.EQ.0.AND.BTEST(FOLDER1_FLAG,10)) THEN
+		    IER = 2
+	            NEW_NEWS = FOLDER1_NUMBER
+	         END IF
+	      END DO
+	      IF (IER.EQ.0) THEN
+	         NEW_NEWS = FOLDER1_NUMBER
+	      ELSE
+	         CALL READ_FOLDER_FILE_KEYNAME_TEMP('a',IER2)
+	         NEW_NEWS = NEWS_F1_COUNT
+	      END IF
+	   ELSE
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+	      IF (CLASS) CALL LOWERCASE(FOLDER1_DESCRIP)
+	      IF (CLASS) NEWS_TEST = .FALSE.
+	      IF (CLASS.AND.FOLDER1.EQ.'a') IER = 2
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF ((INDEX(FOLDER1_BBOARD,'::').EQ.0.OR.NEWS).AND.
+     &		  BTEST(FOLDER1_FLAG,0).AND..NOT.SETPRV_PRIV()) THEN
+		 CALL SET_FOLDER_FILE(1)
+	         IF (NEWS) THEN
+	            IF (OLD_BUFFER.NE.NEWS_ACCESS(FOLDER1_DESCRIP)) THEN
+	               OLD_BUFFER = NEWS_ACCESS(FOLDER1_DESCRIP)
+		       CALL CHKACL(OLD_BUFFER(:TRIM(OLD_BUFFER)),IER2)
+	   	       IF (IER2.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	                  CALL CHECK_ACCESS(OLD_BUFFER(:TRIM(OLD_BUFFER)),
+     &		           USERNAME,READ_ACCESS,-1)
+                       ELSE
+                          READ_ACCESS = 1
+                       END IF
+	            END IF
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		      USERNAME,READ_ACCESS,-1)
+	         END IF
+	      ELSE
+		 READ_ACCESS = 1
+	      END IF
+	      IF (READ_ACCESS) THEN
+	         J = INDEX(FOLDER1_DESCRIP,' ')
+	         IF (J.GT.0) THEN
+	            FSTATUS1(:1) = FOLDER1_DESCRIP(J+1:)
+		 ELSE
+	            FSTATUS1 = ' '
+		    J = TRIM(FOLDER1_DESCRIP) + 1
+	         END IF
+		 IF (.NOT.NEWS_TEST) THEN
+		    IF (NEWS.AND.CLASS) 
+     &			FOLDER1_DESCRIP = FOLDER1_DESCRIP(:J-2)
+	            NUM_FOLDER = NUM_FOLDER + 1
+	            CALL WRITE_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,FOLDER1_COM)
+		 ELSE IF ((.NOT.ACTIVE.OR.(FSTATUS1(:1).NE.'x'.AND..NOT.
+     &			   BTEST(FOLDER1_FLAG,9))).AND.
+     &	                  (.NOT.STORED.OR.BTEST(FOLDER1_FLAG,8)).AND.
+     &			(.NOT.MATCH.OR.STR$MATCH_WILD(FOLDER1_DESCRIP
+     &		        (:J-1),FOLDER_MATCH(:MLEN)))) THEN
+		    GO TO 100
+	         END IF
+	      END IF
+	      IF (PAGING.AND.NUM_FOLDER*NLINE+2.GT.PAGE_LENGTH-4) THEN
+		 IER1 = 1
+		 MORE = .TRUE.
+	      END IF
+	   END IF
+	   IF (FLAG.EQ.1) IER1 = 1
+	END DO
+
+ 	IF (NEWS_TEST) NEWS_TEST = .FALSE.
+
+ 	IF (FLAG.EQ.1) THEN
+	   WRITE (6,'('' Listing aborted.'')')
+	   FOLDER_COUNT = -1
+	   CALL CANCEL_CTRLC_AST
+	   CALL CLOSE_BULLFOLDER
+	   RETURN
+	END IF
+
+	CALL CANCEL_CTRLC_AST
+	CALL CLOSE_BULLFOLDER			! We don't need file anymore
+
+	IF (NUM_FOLDER.EQ.0) THEN
+	   WRITE (6,'('' There are no folders.'')')
+	   FOLDER_COUNT = -1
+	   IF (NEW) LAST_NEWS_READ(1,FOLDER_MAX) = NEW_NEWS
+	   RETURN
+	END IF
+
+C
+C  Folder entries are now in queue.  Output queue entries to screen.
+C
+
+     	SCRATCH_D = SCRATCH_D1			! Init queue pointer to header
+
+100	CALL LIB$ERASE_PAGE(1,1)		! Clear the screen
+
+	IF (.NOT.NEWS) THEN
+	   WRITE (6,'(1X,''Folder'',22X,''Last message'',7X,''Messages'',
+     &		2X,''Owner'',/,1X,80(''-''))')
+	ELSE IF (COUNT) THEN
+	   WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,6X,
+     &		''First        Last  Count'',
+     &		/,1X,<PAGE_WIDTH>(''-''))')
+	ELSE IF (CLASS) THEN
+	   WRITE (6,'(1X,''Class'',/,1X,<PAGE_WIDTH>(''-''))')
+	ELSE IF (SUBSCRIBE) THEN
+	   WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,1X,
+     &		''First        Last   Last Read'',/,1X,<PAGE_WIDTH>(''-''))')
+	ELSE
+	   WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,''Status'',7X,
+     &		''First        Last'',/,1X,<PAGE_WIDTH>(''-''))')
+	END IF
+
+	IF (PAGING.AND.MORE) NUM_FOLDER = NUM_FOLDER - 1
+
+	I = 1
+	DO WHILE ((I.LE.NUM_FOLDER.OR.NEWS_TEST).AND.FLAG.NE.1.AND.
+     &		  FLAG.NE.100)
+	   IF (.NOT.NEWS_TEST) THEN
+	      CALL READ_QUEUE(%VAL(SCRATCH_D),SCRATCH_D,FOLDER1_COM)
+	      I = I + 1
+	   END IF
+	   IF (.NOT.NEWS) THEN
+	      DIFF = COMPARE_BTIM
+     &			(LAST_READ_BTIM(1,FOLDER1_NUMBER+1),F1_NEWEST_BTIM)
+	      IF (F1_NBULL.GT.0) THEN
+	         CALL SYS$ASCTIM(,DATETIME,F1_NEWEST_BTIM,)
+	      ELSE
+	         DATETIME = '      NONE'
+	      END IF
+	      IF (DIFF.GE.0.OR.F1_NBULL.EQ.0) THEN
+	         WRITE (6,1000) ' '//FOLDER1,DATETIME(:17),F1_NBULL,
+     &							FOLDER1_OWNER
+	      ELSE
+	         WRITE (6,1000) '*'//FOLDER1,DATETIME(:17),F1_NBULL,
+     &							FOLDER1_OWNER
+	      END IF
+	   ELSE
+	      IF (NEWS_TEST) UNLOCK 7
+	      FLEN = MIN(80,PAGE_WIDTH-80+49)
+	      IF (SUBSCRIBE) FLEN = MIN(81,PAGE_WIDTH-80+42)
+	      J = INDEX(FOLDER1_DESCRIP,' ')
+	      IF (J.GT.0) THEN
+	         FSTATUS1(:1) = FOLDER1_DESCRIP(J+1:)
+		 IF (FSTATUS1(:1).NE.'=') THEN
+                    FOLDER1_DESCRIP = FOLDER1_DESCRIP(:J-1)
+                 END IF
+	      ELSE
+	         FSTATUS1 = ' '
+	      END IF
+	      IF (BTEST(FOLDER1_FLAG,9)) FSTATUS1 = 'n'
+	      IF (COUNT) THEN
+		 TOTAL_COUNT = TOTAL_COUNT + F1_COUNT
+	         IF (F1_START.LE.F1_NBULL) THEN
+		    WRITE (6,1010) FOLDER1_DESCRIP(:FLEN),
+     &					 F1_START,F1_NBULL,F1_COUNT
+	         ELSE
+		    WRITE (6,1010) FOLDER1_DESCRIP(:FLEN),0,0,0
+		 END IF
+              ELSE IF (CLASS) THEN
+                 WRITE (6,1010) FOLDER1_DESCRIP(:FLEN)
+	      ELSE IF (F1_START.LE.F1_NBULL) THEN
+		 IF (SUBSCRIBE) THEN
+                    NEWS_FOLDER1_NUMBER = FOLDER1_NUMBER
+		    CALL NEWS_GET_NEWEST_MESSAGE1(NEWS_NEW)
+		    IF (NEWS_NEW-1.LT.F1_NBULL.AND.F1_NBULL.GT.0) THEN
+	               WRITE (6,1015) '* '//FOLDER1_DESCRIP(:FLEN-2),
+     &					F1_START,F1_NBULL,NEWS_NEW-1
+		    ELSE
+	               WRITE (6,1015) '  '//FOLDER1_DESCRIP(:FLEN-2),
+     &					F1_START,F1_NBULL,NEWS_NEW-1
+		    END IF
+		 ELSE
+		    WRITE (6,1005) FOLDER1_DESCRIP(:FLEN),
+     &					 FSTATUS1(:1),F1_START,F1_NBULL
+		 END IF
+	      ELSE IF (SUBSCRIBE) THEN
+	         WRITE (6,1015) ' '//FOLDER1_DESCRIP(:FLEN-1),0,0,0
+	      ELSE
+		 WRITE (6,1005) FOLDER1_DESCRIP(:FLEN),FSTATUS1(:1),0,0
+	      END IF
+	   END IF
+	   IF (NLINE.EQ.2) WRITE (6,'(1X,A)') FOLDER1_DESCRIP
+	   LAST_DISPLAY = FOLDER1_NUMBER
+	   IF (NEWS_TEST.AND.FLAG.NE.1) THEN
+	      NUM_FOLDER = NUM_FOLDER + 1
+	      IF (PAGING.AND.
+     &		  NUM_FOLDER*NLINE+2.GE.PAGE_LENGTH-4) MORE = .TRUE.
+	      CALL GET_NEXT_GROUP(MATCH,FOLDER_MATCH,MLEN,FOUND,STORED,
+     &				  FSTATUS1,IER,ACTIVE)
+	      MORE = MORE.AND.FOUND
+	      IF (MORE) THEN
+		 CALL READ_FOLDER_FILE_KEYNUM_TEMP(LAST_DISPLAY,IER)
+              END IF
+	      FOUND = FOUND.AND..NOT.MORE
+	      IF (.NOT.FOUND.AND.FLAG.NE.1) FLAG = 100
+	   END IF
+	END DO
+
+ 	IF (FLAG.EQ.1) THEN
+	   WRITE (6,'('' Listing aborted.'')')
+	   FOLDER_COUNT = -1
+	   CALL CANCEL_CTRLC_AST
+	   CALL CLOSE_BULLFOLDER
+	   RETURN
+	END IF
+
+	IF (NEWS_TEST) THEN
+	   CALL CANCEL_CTRLC_AST
+	   CALL CLOSE_BULLFOLDER
+	END IF
+
+	IF (IER.NE.0.AND..NOT.MORE) THEN	! Outputted all entries?
+	   IF (NEWS.AND.COUNT) THEN
+	      TOTAL_COUNT = -TOTAL_COUNT
+	   ELSE
+	      FOLDER_COUNT = -1			! Yes. Set counter to -1.
+	   END IF
+	   IF (NEW) LAST_NEWS_READ(1,FOLDER_MAX) = NEW_NEWS
+	ELSE
+	   WRITE(6,1100)			! Else say there are more
+	   IF (NEW) LAST_NEWS_READ(1,FOLDER_MAX) = FOLDER1_NUMBER
+	END IF
+
+	RETURN
+
+1000	FORMAT(1X,A26,2X,A17,2X,I8,2X,A12)
+1005	FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-29-1>X,2X,A1,4X,I10,'  ',I10)
+1010	FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-29-1>X,I10,2X,I10,1X,I6)
+1015    FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-36-1>X,2X,I10,2X,I10,2X,I10)
+1100	FORMAT(1X,/,' Press RETURN for more...',/)
+
+	END
+
+
+	SUBROUTINE SET_ACCESS(ACCESS)
+C
+C  SUBROUTINE SET_ACCESS
+C
+C  FUNCTION: Set access on folder for specified ID.
+C
+C  PARAMETERS:
+C	ACCESS  -  Logical: If .true., grant access, if .false. deny access
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	LOGICAL ACCESS,ALL,READONLY
+
+	EXTERNAL CLI$_ABSENT
+
+	CHARACTER ID*64,RESPONSE*4,NEW_NEWS_ACCESS*132
+
+	CHARACTER INPUT*132
+
+	IF (CLI$PRESENT('ALL')) THEN
+	   ALL = .TRUE.
+	ELSE
+	   ALL = .FALSE.
+	END IF
+
+	IF (CLI$PRESENT('READONLY')) THEN
+	   READONLY = .TRUE.
+	ELSE
+	   READONLY = .FALSE.
+	END IF
+
+	IF (ALL) THEN
+	   IER = CLI$GET_VALUE('ACCESS_ID',FOLDER1,LEN) ! Get folder name
+	ELSE
+	   IER = CLI$GET_VALUE('ACCESS_FOLDER',FOLDER1,LEN) ! Get folder name
+	END IF
+
+	IF (IER.EQ.%LOC(CLI$_ABSENT)) FOLDER1 = FOLDER
+	NEWS = INDEX(FOLDER1,'.').GT.0
+
+	IF (NEWS.OR.CLI$PRESENT('CLASS')) THEN
+	   IF (.NOT.CLI$PRESENT('CLASS')) THEN
+	      CALL LOWERCASE(FOLDER1)
+	   ELSE IF (FOLDER1(TRIM(FOLDER1):TRIM(FOLDER1)).NE.'.') THEN
+	      FOLDER1 = FOLDER1(:TRIM(FOLDER1))//'.'
+	   END IF
+	   CALL OPEN_BULLNEWS
+	ELSE
+	   CALL OPEN_BULLFOLDER		! Open folder file
+	END IF
+	CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)	! See if it exists
+	OLD_FOLDER1_FLAG = FOLDER1_FLAG
+	CALL CLOSE_BULLFOLDER
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' ERROR: No such folder exists.'')')
+	ELSE IF (.NOT.FOLDER_ACCESS(USERNAME,FOLDER1_FLAG,FOLDER1_OWNER)) THEN
+	   WRITE (6,
+     &	'('' ERROR: You are not able to modify access to the folder.'')')
+	ELSE IF (CLI$PRESENT('CLASS').AND..NOT.BTEST(FOLDER1_FLAG,0)) THEN
+	   WRITE (6,'('' ERROR: Must use SET NEWS/CLASS/PRIVATE.'')')
+	ELSE
+	   CALL SET_FOLDER_FILE(1)
+	   IF (NEWS) THEN
+	      CALL CHKACL(NEW_NEWS_ACCESS(FOLDER1_DESCRIP),IER)
+	   ELSE
+	      CALL CHKACL
+     &		 (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',IER)
+	   END IF
+	   IF (NEWS.AND.IER.EQ.RMS$_FNF) THEN
+	     CALL SET_PROTECTION
+	     OPEN (UNIT=3,FILE=NEW_NEWS_ACCESS(FOLDER1_DESCRIP),
+     &			STATUS='NEW',IOSTAT=IER)
+	     CLOSE (UNIT=3)
+	     CALL RESET_PROTECTION
+	     IF (IER.NE.0) THEN
+	        WRITE (6,'('' ERROR: Access file cannot be created.'')')
+	        RETURN
+	     END IF
+	     CALL ADD_ACL('*','NONE',IER)
+	     IF (.NOT.IER) THEN
+		WRITE(6,'('' Cannot modify access.'')')
+		CALL SYS_GETMSG(IER)
+		RETURN
+	     END IF
+	   ELSE IF (IER.EQ.RMS$_FNF) THEN
+	     FOLDER_FILE = FOLDER1_FILE
+	     REMOTE_SET_SAVE = REMOTE_SET
+	     REMOTE_SET = .FALSE.
+	     CALL OPEN_BULLFIL
+	     CALL CLOSE_BULLFIL
+	     REMOTE_SET = REMOTE_SET_SAVE
+	     IER = SS$_ACLEMPTY.OR.SS$_NORMAL
+	     CALL SET_FOLDER_FILE(0)
+	   END IF
+	   IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	     IF (.NOT.NEWS.AND.
+     &		 ((ALL.AND..NOT.READONLY).OR.(.NOT.ACCESS))) THEN
+	        WRITE (6,'('' ERROR: Folder is not a private folder.'')')
+		RETURN
+	     END IF
+	     CALL GET_INPUT_PROMPT(RESPONSE,LEN,'Access is presently'
+     &		//' unlimited. Do you want to change this? (Y/N): ')
+	     IF (RESPONSE(:1).NE.'y'.AND.RESPONSE(:1).NE.'Y') THEN
+	       WRITE (6,'('' Access was not changed.'')')
+	       RETURN
+	     ELSE
+	       FOLDER1_FLAG = IBSET(FOLDER1_FLAG,0)
+	       IF (READONLY.AND.ALL) THEN
+	          CALL ADD_ACL('*','R',IER)
+	       ELSE IF (.NOT.ALL) THEN
+	          CALL ADD_ACL('*','NONE',IER)
+	       END IF
+	       IF (.NOT.NEWS) CALL ADD_ACL(FOLDER1_OWNER,'R+W+C',IER)
+	       IF (ALL) THEN		! All finished, so exit
+	        WRITE (6,'('' Access to folder has been modified.'')')
+		GOTO 100
+	       END IF
+	     END IF
+	   END IF
+
+	   IF (ALL) THEN
+	      IF (ACCESS) THEN
+		 CALL DEL_ACL(' ','R+W',IER)
+	         IF (READONLY) THEN
+	            CALL ADD_ACL('*','R',IER)
+	         ELSE IF (.NOT.NEWS) THEN
+		    FOLDER1_FLAG = IBCLR(FOLDER1_FLAG,0)
+	   	    IF (.NOT.NEWS.AND.REMOTE_SET) THEN
+		       CALL SET_FOLDER_FILE(1)
+		       FOLDER_FILE = FOLDER1_FILE
+		       REMOTE_SET_SAVE = REMOTE_SET
+		       REMOTE_SET = .FALSE.
+		       CALL OPEN_BULLDIR
+		       CALL OPEN_BULLFIL
+		       CALL CLOSE_BULLFIL_DELETE
+		       CALL CLOSE_BULLDIR_DELETE
+		       REMOTE_SET = REMOTE_SET_SAVE
+		       CALL SET_FOLDER_FILE(0)
+		    END IF
+		 END IF
+	      ELSE
+		 CALL DEL_ACL('*','R',IER)
+	      END IF
+	      IF (.NOT.IER) THEN
+		 WRITE(6,'('' Cannot modify access.'')')
+		 CALL SYS_GETMSG(IER)
+	      END IF
+	   END IF
+
+	   DO WHILE (CLI$GET_VALUE('ACCESS_ID',INPUT,ILEN)
+     &	    .NE.%LOC(CLI$_ABSENT).AND..NOT.ALL)
+	      IER = SYS_TRNLNM(INPUT,INPUT)
+	      IF (INPUT(:1).EQ.'@') THEN
+		 ILEN = INDEX(INPUT,',') - 1
+		 IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+		 OPEN (UNIT=3,STATUS='OLD',FILE=INPUT(2:ILEN),
+     &			DEFAULTFILE='.DIS',IOSTAT=IER)
+		 IF (IER.NE.0) THEN
+		    WRITE (6,'('' ERROR: Cannot find file '',A)')
+     &					INPUT(2:ILEN)
+		    RETURN
+		 END IF
+		 READ (3,'(A)',IOSTAT=IER) INPUT
+		 IF (IER.NE.0) THEN
+		    CLOSE (UNIT=3)
+		    INPUT = ' '
+		 ELSE
+		    FILE_OPEN = .TRUE.
+		 END IF
+	      ELSE
+		 FILE_OPEN = .FALSE.
+	      END IF
+	      DO WHILE (TRIM(INPUT).GT.0)
+	         COMMA = INDEX(INPUT,',')
+		 IF (INDEX(INPUT,'[').EQ.0.AND.INDEX(INPUT,']').GT.0.AND.
+     &		    ID(:1).EQ.'[') INPUT = ID(:TRIM(ID))//','//INPUT
+		 IF (INPUT(:1).EQ.'['.AND.INDEX(INPUT,']').GT.0)
+     &		    COMMA = INDEX(INPUT,']') + 1
+		 IF (INPUT(:1).EQ.'"'.AND.INDEX(INPUT(2:),'"').GT.0)
+     &		    COMMA = INDEX(INPUT(2:),'"') + 2
+		 IF (INPUT(:1).EQ.'['.AND.INDEX(INPUT,']').EQ.0) COMMA = 0
+	         IF (COMMA.GT.0) THEN
+		    ID = INPUT(1:COMMA-1)
+		    INPUT = INPUT(COMMA+1:)
+	            ILEN = TRIM(ID)
+	         ELSE
+		    ID = INPUT
+		    INPUT = ' '
+	            ILEN = TRIM(ID)
+	         END IF
+ 	         IF (.NOT.NEWS.AND.ID.EQ.FOLDER1_OWNER) THEN
+	            WRITE (6,'('' ERROR: Cannot modify access'',
+     &			       '' for owner of folder.'')')
+		 ELSE IF (ID(:1).NE.'['.OR.INDEX(ID,']').NE.0) THEN
+		    IF (ILEN.EQ.0) THEN
+		       IER = SS$_IVIDENT
+		    ELSE IF (ACCESS) THEN
+	               IF (READONLY) THEN
+	                  CALL ADD_ACL(ID,'R',IER)
+		       ELSE
+	                  CALL ADD_ACL(ID,'R+W',IER)
+		       END IF
+	            ELSE
+	               CALL DEL_ACL(ID,'R+W',IER)
+	               IF (.NOT.IER) CALL DEL_ACL(ID,'R',IER)
+	            END IF
+	            IF (.NOT.IER) THEN
+		       WRITE(6,'('' Cannot modify access for '',A,
+     &					''.'')') ID(:ILEN)
+		       CALL SYS_GETMSG(IER)
+		    ELSE
+		       WRITE(6,'('' Access modified for '',A,''.'')')
+     &				ID(:ILEN)
+		    END IF
+		 END IF
+	         IF (TRIM(INPUT).EQ.0.AND.FILE_OPEN) THEN
+		    READ (3,'(A)',IOSTAT=IER) INPUT
+		    IF (IER.NE.0) THEN
+		       CLOSE (UNIT=3)
+		       INPUT = ' '
+		       FILE_OPEN = .FALSE.
+		    END IF
+		 END IF
+	      END DO
+	   END DO
+	   
+100	   IF (OLD_FOLDER1_FLAG.NE.FOLDER1_FLAG) THEN
+	      IF (NEWS) THEN
+	         CALL OPEN_BULLNEWS
+	      ELSE
+	         CALL OPEN_BULLFOLDER
+	      END IF
+	      OLD_FOLDER1_FLAG = FOLDER1_FLAG
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	      FOLDER1_FLAG = OLD_FOLDER1_FLAG
+	      CALL REWRITE_FOLDER_FILE_TEMP(IER)
+	      CALL CLOSE_BULLFOLDER
+	   END IF
+	END IF
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CHKACL(FILENAME,IERACL)
+C
+C  SUBROUTINE CHKACL
+C
+C  FUNCTION: Checks ACL of given file.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C	IERACL   - Error returned for attempt to open file.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) FILENAME
+
+	INCLUDE '($ACLDEF)'
+	INCLUDE '($SSDEF)'
+
+	CHARACTER*256 ACLENT
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(256,ACL$C_READACL,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IERACL=SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST),,,)
+
+	IF (IERACL.EQ.SS$_ACLEMPTY) THEN
+	   IERACL = SS$_NORMAL.OR.IERACL
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CHECK_ACCESS(FILENAME,USERNAME,READ_ACCESS,WRITE_ACCESS)
+C
+C  SUBROUTINE CHECK_ACCESS
+C
+C  FUNCTION: Checks ACL of given file.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C	USERNAME - Name of user to check access for.
+C	READ_ACCESS - Error returned indicating read access.
+C	WRITE_ACCESS - Error returned indicating write access.
+C		       If initially set to -1, indicates just
+C		       folder for read access.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER FILENAME*(*),USERNAME*(*),ACE*256,OUTPUT*80
+
+	INCLUDE '($ACLDEF)'
+	INCLUDE '($CHPDEF)'
+	INCLUDE '($ARMDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,CHP$_FLAGS,%LOC(FLAGS))
+	CALL ADD_2_ITMLST(4,CHP$_ACCESS,%LOC(ACCESS))
+	CALL ADD_2_ITMLST(LEN(ACE),CHP$_MATCHEDACE,%LOC(ACE))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	FLAGS = 0		! Default is no access
+
+	ACCESS = ARM$M_READ	! Check if user has read access
+	READ_ACCESS=SYS$CHECK_ACCESS(ACL$C_FILE,FILENAME,USERNAME,
+     &		%VAL(ACL_ITMLST))
+
+
+	IF (ICHAR(ACE(:1)).NE.0) THEN
+	   CALL SYS$FORMAT_ACL(ACE,,OUTPUT,,,,)
+	   IF (INDEX(OUTPUT,'=*').NE.0.AND.
+     &		INDEX(OUTPUT,'READ').EQ.0) READ_ACCESS = 0
+	ELSE IF (ICHAR(ACE(:1)).EQ.0.AND.READ_ACCESS) THEN
+	   READ_ACCESS = 0
+	END IF
+
+	IF (WRITE_ACCESS.EQ.-1) THEN	! Only check read access
+	   RETURN
+	ELSE IF (READ_ACCESS.EQ.0) THEN	! If no read access, then of
+	   WRITE_ACCESS = 0		! course there is no write access.
+	   RETURN
+	END IF
+
+	ACCESS = ARM$M_WRITE	! Check if user has write access
+	WRITE_ACCESS=SYS$CHECK_ACCESS(ACL$C_FILE,FILENAME,USERNAME,
+     &		%VAL(ACL_ITMLST))
+
+	IF (ICHAR(ACE(:1)).NE.0) THEN
+	   CALL SYS$FORMAT_ACL(ACE,,OUTPUT,,,,)
+	   IF (INDEX(OUTPUT,'=*').NE.0.AND.
+     &		INDEX(OUTPUT,'WRITE').EQ.0) WRITE_ACCESS = 0
+	ELSE IF (ICHAR(ACE(:1)).EQ.0.AND.WRITE_ACCESS) THEN
+	   WRITE_ACCESS = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOWACL(FILENAME)
+C
+C  SUBROUTINE SHOWACL
+C
+C  FUNCTION: Shows users who are allowed to read private bulletin.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER*(*) FILENAME
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,ACL$C_ACLLENGTH,%LOC(ACLLENGTH))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST),,,)
+
+	CALL LIB$GET_VM(ACLLENGTH+8,ACLSTR)
+	CALL MAKE_CHAR(%VAL(ACLSTR),ACLLENGTH,ACLLENGTH)
+
+	CALL READACL(FILENAME,%VAL(ACLSTR),ACLLENGTH)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE FOLDER_FILE_ROUTINES
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) KEY_NAME
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /NEWS_OPEN/ NEWS_OPEN
+
+	ENTRY WRITE_FOLDER_FILE(IER)
+
+	IF (NEWS_OPEN) CALL FOLDER_TO_NEWS
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      WRITE (7,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      WRITE (7,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	RETURN
+
+        ENTRY WRITE_FOLDER_FILE_TEMP(IER)
+
+        IF (NEWS_OPEN) CALL FOLDER1_TO_NEWS
+
+        DO WHILE (REC_LOCK(IER))
+           IF (NEWS_OPEN) THEN
+              WRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+           ELSE
+              WRITE (7,IOSTAT=IER) FOLDER1_COM
+           END IF
+        END DO
+
+        RETURN
+
+	ENTRY REWRITE_FOLDER_FILE(IER)
+
+	IF (NEWS_OPEN) THEN
+	   CALL FOLDER_TO_NEWS
+	   REWRITE (7,IOSTAT=IER) NEWS_FOLDER_COM
+	ELSE
+	   REWRITE (7,IOSTAT=IER) FOLDER_COM
+	END IF
+
+	RETURN
+
+	ENTRY REWRITE_FOLDER_FILE_TEMP(IER) 
+
+	IF (NEWS_OPEN) THEN
+	   CALL FOLDER1_TO_NEWS
+	   REWRITE (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	ELSE
+	   REWRITE (7,IOSTAT=IER) FOLDER1_COM
+	END IF
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_TEMP(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM(KEY_NUMBER,IER)
+
+	SAVE_FOLDER_NUMBER = FOLDER_NUMBER
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	FOLDER_NUMBER = SAVE_FOLDER_NUMBER
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM_GT(KEY_NUMBER,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM_TEMP(KEY_NUMBER,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEY=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNUM_GT_TEMP(KEY_NUMBER,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEYGT=KEY_NUMBER,KEYID=1,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAME_TEMP(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAMEGE_TEMP(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGE=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEYGE=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAMEGT_TEMP(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEYGT=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER1_COM
+	   ELSE
+	      READ (7,KEYGT=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER1_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER1
+
+	RETURN
+
+	ENTRY READ_FOLDER_FILE_KEYNAME(KEY_NAME,IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   IF (NEWS_OPEN) THEN
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) NEWS_FOLDER_COM
+	   ELSE
+	      READ (7,KEY=KEY_NAME,KEYID=0,IOSTAT=IER) FOLDER_COM
+	   END IF
+	END DO
+
+	IF (NEWS_OPEN.AND.IER.EQ.0) CALL NEWS_TO_FOLDER
+
+	RETURN
+
+	END
+
+
+	SUBROUTINE USER_FILE_ROUTINES
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE '($FORIOSDEF)'
+
+	CHARACTER*(*) KEY_NAME
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER*12 SAVE_USERNAME
+
+	ENTRY READ_USER_FILE(IER)
+
+	SAVE_USERNAME = USERNAME
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,IOSTAT=IER) USER_ENTRY
+	END DO
+
+	TEMP_USER = USERNAME
+	USERNAME = SAVE_USERNAME
+
+	RETURN
+
+	ENTRY READ_USER_FILE_KEYNAME(KEY_NAME,IER)
+
+	SAVE_USERNAME = USERNAME
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY=KEY_NAME,IOSTAT=IER) USER_ENTRY
+	END DO
+
+	USERNAME = SAVE_USERNAME
+	TEMP_USER = KEY_NAME
+
+	RETURN
+
+	ENTRY READ_USER_FILE_HEADER(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (4,KEY='            ',IOSTAT=IER) USER_HEADER
+	   IF (IER.EQ.FOR$IOS_ATTACCNON) THEN
+	      WRITE (4,FMT=USER_FMT,IOSTAT=IER)
+     &		 USER_HEADER_KEY,NEWEST_BTIM,
+     &	         BBOARD_BTIM,PRV$M_OPER.OR.PRV$M_CMKRNL.OR.
+     &	         PRV$M_SETPRV,(0,I=1,FLONG*4-1)
+	      IER = FOR$IOS_SPERECLOC
+	   END IF
+	END DO
+
+	RETURN
+
+	ENTRY WRITE_USER_FILE_NEW(IER)
+
+	DO I=1,FLONG
+	   SET_FLAG(I) = SET_FLAG_DEF(I)
+	   BRIEF_FLAG(I) = BRIEF_FLAG_DEF(I)
+	   NOTIFY_FLAG(I) = NOTIFY_FLAG_DEF(I)
+	END DO
+
+	ENTRY WRITE_USER_FILE(IER)
+
+	DO WHILE (REC_LOCK(IER))
+	   WRITE (4,IOSTAT=IER) USER_ENTRY
+	END DO
+
+	RETURN
+
+	END
+
+
+
+	CHARACTER*(*) FUNCTION NEW_NEWS_ACCESS(IFILE)
+ 
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER IFILE*(*),FILE*80
+
+        FILE = IFILE
+	
+	DO I=1,TRIM(FILE)
+	   IF (FILE(I:I).EQ.'.') FILE(I:I) = '_'
+	END DO
+
+	FILE = FILE(:INDEX(FILE,' ')-1)
+	IF (FILE(TRIM(FILE):TRIM(FILE)).EQ.'_') FILE = FILE(:TRIM(FILE)-1)
+
+	NEW_NEWS_ACCESS = 
+     &	   NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//FILE(:TRIM(FILE))
+     &	   //'.ACCESS'
+
+	RETURN
+	END
+
+
+
+
+	CHARACTER*(*) FUNCTION NEWS_ACCESS(IFILE)
+ 
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER IFILE*(*),FILE*80
+
+        FILE = IFILE
+	
+	DO I=1,TRIM(FILE)
+	   IF (FILE(I:I).EQ.'.') FILE(I:I) = '_'
+	END DO
+
+	FILE = FILE(:INDEX(FILE,' ')-1)
+	IF (FILE(TRIM(FILE):TRIM(FILE)).EQ.'_') FILE = FILE(:TRIM(FILE)-1)
+
+	C = 0
+
+	DO WHILE (TRIM(FILE).GT.0.AND..NOT.LIB$FIND_FILE(
+     &	   NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY))//FILE(:TRIM(FILE))
+     &	   //'.ACCESS',NEWS_ACCESS,C))
+	   L = LAST_INDEX(FILE,'_')-1
+	   IF (L.LE.0) THEN
+	      FILE = ' '
+	   ELSE
+	      FILE = FILE(:L)
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION LAST_INDEX(INPUT,FIND)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,FIND
+
+        F = LEN(FIND)
+
+	DO LAST_INDEX=LEN(INPUT)-F+1,F,-1
+           IF (INPUT(LAST_INDEX:LAST_INDEX+F-1).EQ.FIND) RETURN
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NEXT_GROUP(MATCH,FOLDER_MATCH,MLEN,FOUND,STORED,
+     &				  STAT,IER,ACTIVE)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	CHARACTER*(*) STAT,FOLDER_MATCH
+
+	CHARACTER NEWS_ACCESS*132
+
+	FOUND = .FALSE.
+	STAR = INDEX(FOLDER_MATCH,'*')
+	ONE = STAR.EQ.0.AND.TRIM(FOLDER_MATCH).GT.0
+	START = .FALSE.
+	IF (STAR.GT.1)
+     &	   START = FOLDER_MATCH(:STAR-1).NE.FOLDER1(:STAR-1)
+	STARTNOW = START
+
+	DO WHILE (FLAG.NE.1.AND.IER.EQ.0.AND..NOT.FOUND) 
+	   IF (ONE) THEN
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &		(FOLDER_MATCH(:TRIM(FOLDER_MATCH)),IER)
+	      FOLDER_MATCH = ' '
+	   ELSE IF (STARTNOW) THEN 
+	      CALL READ_FOLDER_FILE_KEYNAMEGE_TEMP
+     &				       (FOLDER_MATCH(:STAR-1),IER)
+	      STARTNOW = .FALSE.
+	   ELSE
+	      CALL READ_FOLDER_FILE_TEMP(IER)
+	   END IF
+	   J = INDEX(FOLDER1_DESCRIP,' ')
+	   IF (J.GT.0) THEN
+	      STAT(:1) = FOLDER1_DESCRIP(J+1:)
+	   ELSE
+	      STAT = ' '
+	      J = TRIM(FOLDER1_DESCRIP) + 1
+	   END IF
+	   IF (IER.EQ.0.AND.(.NOT.ACTIVE.OR.(STAT(:1).NE.'x'.AND.
+     &		.NOT.BTEST(FOLDER1_FLAG,9))).AND.
+     &		(.NOT.STORED.OR.BTEST(FOLDER1_FLAG,8)).AND.
+     &		(ONE.OR..NOT.MATCH.OR.STR$MATCH_WILD(FOLDER1_DESCRIP
+     &		(:J-1),FOLDER_MATCH(:MLEN)))) THEN
+	      IF (BTEST(FOLDER1_FLAG,0)) THEN
+		 IF (OLD_BUFFER.NE.NEWS_ACCESS(FOLDER1_DESCRIP)) THEN
+		    OLD_BUFFER = NEWS_ACCESS(FOLDER1_DESCRIP)
+		    CALL CHKACL(OLD_BUFFER(:TRIM(OLD_BUFFER)),IER2)
+	   	    IF (IER2.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+		       CALL CHECK_ACCESS(OLD_BUFFER
+     &			 (:TRIM(OLD_BUFFER)),USERNAME,FOUND1,-1)
+ 		    ELSE
+		       FOUND1 = .TRUE.
+		    END IF
+		 END IF
+		 FOUND = FOUND1
+	      ELSE
+		 FOUND = .TRUE.
+	      END IF
+	   ELSE IF (IER.EQ.0.AND.START) THEN 
+	      IF (FOLDER_MATCH(:STAR-1).NE.FOLDER1(:STAR-1)) RETURN
+	   END IF
+	   IF (ONE) RETURN
+	END DO
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin6.for b/decus/vmslt98a/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..948cd3f32cda6c5459dd5f21690e16905dc64867
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin6.for
@@ -0,0 +1,2811 @@
+C
+C  BULLETIN6.FOR, Version 9/15/95
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE CLOSE_FILE
+C
+C  SUBROUTINE CLOSE_FILE
+C
+C  FUNCTION: To close out the bulletin files and enable CTRL-C & -Y
+C
+
+        IMPLICIT INTEGER (A-Z)
+
+	COMMON /BULLFIL/ BULLFIL
+	DATA BULLFIL /0/
+
+	DATA LUN /0/
+
+	ENTRY CLOSE_BULLINF
+	LUN = LUN + 1			! Unit = 9
+
+	ENTRY CLOSE_SYSUAF
+	LUN = LUN + 1			! Unit = 8
+
+	ENTRY CLOSE_BULLNEWS
+	ENTRY CLOSE_BULLFOLDER
+	LUN = LUN + 3			! Unit = 7
+
+	ENTRY CLOSE_BULLUSER
+	LUN = LUN + 2			! Unit = 4
+
+	ENTRY CLOSE_BULLDIR
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY CLOSE_BULLFIL
+	LUN = LUN + 1			! Unit = 1
+
+	CALL ENABLE_CTRL
+
+	CLOSE (UNIT=LUN)
+
+        IF (LUN.EQ.1.AND.BULLFIL.GT.0) BULLFIL = -BULLFIL
+
+	LUN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE CLOSE_FILE_DELETE
+
+	IMPLICIT INTEGER (A-Z)
+
+        COMMON /BULLFIL/ BULLFIL
+
+	DATA LUN /0/
+
+	ENTRY CLOSE_BULLDIR_DELETE
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY CLOSE_BULLFIL_DELETE
+	LUN = LUN + 1			! Unit = 1
+
+	CALL ENABLE_CTRL
+
+	CLOSE (UNIT=LUN,STATUS='DELETE')
+
+        IF (LUN.EQ.1.AND.BULLFIL.GT.0) BULLFIL = -BULLFIL
+
+	LUN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE OPEN_FILE(UNIT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+        COMMON /NEWS_OPEN/ NEWS_OPEN
+
+        COMMON /BULLFIL/ BULLFIL
+
+	COMMON /NEWSLIST/ NEWSLIST
+
+	COMMON /DIRLIST/ DIRLIST
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+
+	DATA LUN /0/
+
+	LUN = UNIT - 14			! 14 gets added to LUN
+
+	ENTRY OPEN_BULLNEWS
+	LUN = LUN + 5			! Unit = 14
+
+	ENTRY OPEN_BULLINF
+	LUN = LUN + 1			! Unit = 9
+
+	ENTRY OPEN_SYSUAF
+	LUN = LUN + 1			! Unit = 8
+
+	ENTRY OPEN_BULLFOLDER
+	LUN = LUN + 3			! Unit = 7
+
+	ENTRY OPEN_BULLUSER
+	LUN = LUN + 2			! Unit = 4
+
+	ENTRY OPEN_BULLDIR
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY OPEN_BULLFIL
+	LUN = LUN + 1			! Unit = 1
+
+	IER = 0
+
+	NTRIES = 0
+
+	CALL SET_PROTECTION
+
+	CALL DISABLE_CTRL		! No breaks while file is open
+
+	IF (LUN.EQ.2.AND.REMOTE_SET.EQ.4) THEN
+	   TRY = 0
+	   CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    IF (DIRLIST) THEN 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      BUFFERCOUNT=127,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    ELSE 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    END IF
+
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU.AND.TRY.EQ.0) THEN
+	       BULLNEWSDIR_FILE = 'BULLNEWSDIR.DAT'
+	       CALL ADD_DIRECTORY(BULLNEWSDIR_FILE)
+	       TRY = 1
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	    ELSE IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+	       OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	        STATUS='NEW',FORM='UNFORMATTED',SHARED,
+     &	        RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	        KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	        57:64:CHARACTER),ACCESS='KEYED')
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN.OR.
+     &		IER.EQ.FOR$IOS_INVKEYSPE) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       LUN = 0
+	       CALL CONVERT_BULLNEWSDIR
+	       NTRIES = 0
+	       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+            ELSE IF (IER.EQ.FOR$IOS_OPEFAI) THEN
+	       CALL ERRSNS(IDUMMY,IER1)
+               IF (IER1.EQ.RMS$_DNF) THEN
+	          IER2 =  LIB$CREATE_DIR(BULLNEWSDIR_FILE(:
+     &			INDEX(BULLNEWSDIR_FILE,']')))
+	          IF (IER2) IDUMMY = FILE_LOCK(IER,IER1)
+	       END IF
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   DIR_NUM = -1
+	ELSE IF (LUN.EQ.2.AND..NOT.REMOTE_SET) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	       OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	        //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	        RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	        KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	    ELSE IF (IER.EQ.0) THEN
+	       INQUIRE(UNIT=2,RECORDSIZE=ASK_SIZE)
+	       IF (ASK_SIZE.NE.DIR_RECORD_LENGTH/4) THEN
+	          CLOSE (UNIT=2)
+	          IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	          CALL CONVERT_BULLFILES
+		  NTRIES = 0
+	       END IF
+	    ELSE IF (IER.EQ.FOR$IOS_INCFILORG) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLDIRS
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   DIR_NUM = -1
+	END IF
+
+	IF (LUN.EQ.1.AND..NOT.REMOTE_SET) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    IF (REMOTE_SET.EQ.4) THEN
+	      IF (BULLFIL.NE.1) CALL SET_BULLFIL_NAME
+	      OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='UNKNOWN',IOSTAT=IER,SHARED,
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	      FORM='UNFORMATTED')
+	      IF (IER.EQ.0) THEN
+	         DO WHILE (REC_LOCK(IER2))
+                    READ (1'1,IOSTAT=IER2) NBLOCK
+	         END DO
+                 IF (IER2.NE.0) THEN
+                    NBLOCK = 1
+                    WRITE (1'1,IOSTAT=IER2) NBLOCK
+		 END IF
+                 BULLFIL = 1
+              END IF
+            ELSE
+	      OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='UNKNOWN',IOSTAT=IER,
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	      FORM='UNFORMATTED')
+            END IF
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLFILE
+	       NTRIES = 0
+            ELSE IF (IER.EQ.FOR$IOS_OPEFAI) THEN
+	       CALL ERRSNS(IDUMMY,IER1)
+               IF (IER1.EQ.RMS$_DNF) THEN
+	          IER2 =  LIB$CREATE_DIR(
+     &				FOLDER_FILE(:INDEX(FOLDER_FILE,']')))
+	          IF (IER2) IDUMMY = FILE_LOCK(IER,IER1)
+	       END IF
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	END IF
+
+	IF (LUN.EQ.4) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=7+FLONG*4,
+     &	     ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	     KEY=(1:12:CHARACTER))
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	     OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='UNKNOWN',
+     &	      ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=28+FLONG*16,
+     &	      FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	      KEY=(1:12:CHARACTER))
+	     WRITE (4,FMT=USER_FMT) USER_HEADER_KEY,NEWEST_BTIM,
+     &	      BBOARD_BTIM,PRV$M_OPER.OR.PRV$M_CMKRNL.OR.
+     &	      PRV$M_SETPRV,(0,I=1,FLONG*4-1)
+	     CLOSE (UNIT=4)
+	     IDUMMY = FILE_LOCK(IER,IER1)
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	     IDUMMY = FILE_LOCK(IER,IER1)
+	     CALL CONVERT_USERFILE
+	     NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	END IF
+
+	IF (LUN.EQ.7) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	     RECORDSIZE=FOLDER_RECORD/4,
+     &	     ORGANIZATION='INDEXED',IOSTAT=IER)
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	      FOLDER1 = 'GENERAL'
+	      FOLDER1_OWNER = 'SYSTEM'
+	      FOLDER1_DESCRIP = 'Default general bulletin folder.'
+	      FOLDER1_BBOARD = 'NONE'
+	      FOLDER1_BBEXPIRE = 14
+	      NBULL = 0
+	      OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='UNKNOWN',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=FOLDER_RECORD,
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER2,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER))
+              CALL SYS_BINTIM('5-NOV-1982 00:00:00.00',
+     &				NEWS_F_NEWEST_BTIM)
+              CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,FOLDER1_CREATED_DATE)
+	      WRITE (7,FMT=FOLDER_FMT,IOSTAT=IER2)
+     &		FOLDER1,0,FOLDER1_CREATED_DATE,FOLDER1_OWNER,FOLDER1_DESCRIP
+     &		,FOLDER1_BBOARD,FOLDER1_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &		,NBULL,F_NEWEST_BTIM,4,0,F_NEWEST_NOSYS_BTIM,0,0,0
+						! 4 means system folder
+	      CLOSE (UNIT=7)
+	      IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	      IDUMMY = FILE_LOCK(IER,IER1)
+	      CALL CONVERT_BULLFOLDER(BULLFOLDER_FILE)
+	      NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .FALSE.
+	END IF
+
+	IF (LUN.EQ.14) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+            IF (NEWSLIST) THEN
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	        BUFFERCOUNT=127,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER)
+	    ELSE
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER)
+            END IF
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+	      OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='UNKNOWN',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD,
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER2,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER,
+     &          57:64:CHARACTER:DESCENDING))
+	      CLOSE (UNIT=7)
+	      IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	    ELSE IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	      IDUMMY = FILE_LOCK(IER,IER1)
+	      CALL CONVERT_BULLNEWS(BULLNEWS_FILE)
+	      NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.10) CALL TIMER_ERR(LUN)
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .TRUE.
+	END IF
+
+	IF (LUN.EQ.9) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='UNKNOWN',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=FOLDER_MAX*2+3,
+     &	     IOSTAT=IER,ORGANIZATION='INDEXED',
+     &	     KEY=(1:12:CHARACTER))
+	     IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_INFFILE
+	       NTRIES = 0
+	     END IF
+	     NTRIES = 0
+	     IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'(
+     &	    '' Cannot open file in OPEN_FILE, unit = '',I)') LUN
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	   CALL ENABLE_CTRL_EXIT	! Enable CTRL-Y & -C & EXIT
+	END IF
+
+	LUN = 0
+
+	CALL RESET_PROTECTION
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE TIMER_ERR(UNIT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*14 NAMES(6)
+	DATA NAMES/'directory','message','BULLUSER.DAT','BULLFOLDER.DAT',
+     &			'BULLINF.DAT','BULLNEWS.DAT'/
+	INTEGER NAME(14)
+	DATA NAME/2,1,0,3,0,0,4,0,5,0,0,0,0,6/
+
+	IF (TEST_BULLCP().NE.2) THEN	! If BULLCP process, don't log error
+	   WRITE(6,'('' ERROR: Unable to open file: '',A)')
+     &			NAMES(NAME(UNIT))(:TRIM(NAMES(NAME(UNIT))))
+	   IF (UNIT.EQ.14) THEN 
+	      WRITE (6,'('' Database conversion in progress.  Try later.'')')
+	   ELSE
+	      WRITE (6,'('' Please try again later.'')')
+	   END IF
+	END IF
+
+	CALL ENABLE_CTRL_EXIT		! No breaks while file is open
+	END
+
+
+
+	SUBROUTINE OPEN_FILE_SHARED
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FORIOSDEF)'
+
+	INCLUDE '($RMSDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+        COMMON /NEWS_OPEN/ NEWS_OPEN
+
+        COMMON /BULLFIL/ BULLFIL
+
+	EXTERNAL LNM_MODE_EXEC,ENABLE_CTRL_EXIT
+C
+C  The following 2 files were used prior to V1.1.
+C
+	CHARACTER*80 BULLDIR_FILE /'BULL_DIR:BULLDIR.DAT'/
+	CHARACTER*80 BULLETIN_FILE /'BULL_DIR:BULLETIN.DAT'/
+
+	COMMON /NEWSLIST/ NEWSLIST
+	DATA NEWSLIST/0/
+
+	COMMON /DIRLIST/ DIRLIST
+	DATA DIRLIST/0/
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+  
+	CHARACTER*44 SAVE_FOLDER
+	DATA SAVE_BLOCK/-1/
+
+	CHARACTER*14 NAMES(6)
+	DATA NAMES/'directory','message','BULLUSER.DAT','BULLFOLDER.DAT',
+     &			'BULLINF.DAT','BULLNEWS.DAT'/
+	INTEGER NAME(14)
+	DATA NAME/2,1,0,3,0,0,4,0,5,0,0,0,0,6/
+
+	DATA LUN /0/
+
+	ENTRY OPEN_BULLNEWS_SHARED
+	LUN = LUN + 5			! Unit = 14
+
+	ENTRY OPEN_BULLINF_SHARED
+	LUN = LUN + 1			! Unit = 9
+
+	ENTRY OPEN_SYSUAF_SHARED
+	LUN = LUN + 1			! Unit = 8
+
+	ENTRY OPEN_BULLFOLDER_SHARED
+	LUN = LUN + 3			! Unit = 7
+
+	ENTRY OPEN_BULLUSER_SHARED
+	LUN = LUN + 2			! Unit = 4
+
+	ENTRY OPEN_BULLDIR_SHARED
+	LUN = LUN + 1			! Unit = 2
+
+	ENTRY OPEN_BULLFIL_SHARED
+	LUN = LUN + 1			! Unit = 1
+
+	IER = 0
+
+	NTRIES = 0
+
+	CALL DISABLE_CTRL
+
+	IF (LUN.EQ.2.AND.REMOTE_SET.EQ.4) THEN
+	   CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    IF (DIRLIST) THEN 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      BUFFERCOUNT=127,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    ELSE 
+	     OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	      STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	      57:64:CHARACTER),ACCESS='KEYED')
+	    END IF
+	    IF (IER.EQ.FOR$IOS_INCRECLEN.OR.
+     &		IER.EQ.FOR$IOS_INVKEYSPE) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       LUN = 0
+	       CALL CONVERT_BULLNEWSDIR
+	       LUN = 2
+	       NTRIES = 0
+	       CALL SET_BULLNEWSDIR_FILE(FOLDER_NUMBER)
+            ELSE IF (IER.EQ.FOR$IOS_OPEFAI) THEN
+	       CALL ERRSNS(IDUMMY,IER1)
+               IF (IER1.EQ.RMS$_DNF) THEN
+	          IER1 =  LIB$CREATE_DIR(BULLNEWSDIR_FILE(:
+     &			INDEX(BULLNEWSDIR_FILE,']')))
+	          IF (IER1) IDUMMY = FILE_LOCK(IER,IER1)
+	       END IF
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
+	   END DO
+	   DIR_NUM = -1
+	ELSE IF (LUN.EQ.2.AND..NOT.REMOTE_SET) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+
+	    OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,SHARED,
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	    IF (IER.EQ.FOR$IOS_FILNOTFOU.AND.(FOLDER_NUMBER.EQ.0
+     &		.OR.FOLDER.EQ.'GENERAL')) THEN
+	       IER2 = LIB$RENAME_FILE(BULLETIN_FILE,'GENERAL.BULLFIL')
+	       IER2 = LIB$RENAME_FILE(BULLDIR_FILE,'GENERAL.BULLDIR')
+	       IF (IER2) IDUMMY = FILE_LOCK(IER,IER1) ! Don't break out of loop
+	    ELSE IF (IER.EQ.0) THEN
+	       INQUIRE(UNIT=2,RECORDSIZE=ASK_SIZE)
+	       IF (ASK_SIZE.NE.DIR_RECORD_LENGTH/4) THEN
+	          CLOSE (UNIT=2)
+	          IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	          CALL CONVERT_BULLFILES
+		  NTRIES = 0
+	       END IF
+	    ELSE IF (IER.EQ.FOR$IOS_INCFILORG) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLDIRS
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	   DIR_NUM = -1
+	END IF
+
+	IF (LUN.EQ.1.AND.REMOTE_SET.AND.(SAVE_BLOCK.NE.BLOCK.OR.
+     &		SAVE_FOLDER.NE.FOLDER)) THEN
+	   CALL REMOTE_READ_MESSAGE(BULL_POINT,IER)
+	   IF (IER.GT.0) THEN
+	      CALL ERROR_AND_EXIT
+	   ELSE
+	      SAVE_BLOCK = BLOCK
+	      SAVE_FOLDER = FOLDER
+	      CALL GET_REMOTE_MESSAGE(IER)
+	      IER = 0
+	   END IF
+	ELSE IF (LUN.EQ.1.AND..NOT.REMOTE_SET) THEN
+	   SAVE_BLOCK = -1
+	   IF (REMOTE_SET.EQ.4.AND.BULLFIL.NE.2) CALL SET_BULLFIL_NAME
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	     OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='OLD',
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	      FORM='UNFORMATTED',IOSTAT=IER,SHARED,READONLY)
+	    IF (REMOTE_SET.EQ.4) THEN
+	      IF (IER.EQ.0) THEN
+	         DO WHILE (REC_LOCK(IER2))
+                    READ (1'1,IOSTAT=IER2) NBLOCK
+	         END DO
+                 IF (IER2.NE.0) NBLOCK = 1
+                 BULLFIL = 2
+              END IF
+            END IF
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_BULLFILE
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	END IF
+
+	IF (LUN.EQ.4) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='OLD',
+     &	    ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=7+FLONG*4,
+     &	    IOSTAT=IER,ORGANIZATION='INDEXED',SHARED,
+     &	    KEY=(1:12:CHARACTER))
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)
+	       CALL CONVERT_USERFILE
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	END IF
+
+	IF (LUN.EQ.7) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='OLD',
+     &	    RECORDSIZE=FOLDER_RECORD/4,
+     &	    ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	    IOSTAT=IER,ORGANIZATION='INDEXED',SHARED)
+
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)
+	       CALL CONVERT_BULLFOLDER(BULLFOLDER_FILE)
+	       NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .FALSE.
+	END IF
+
+	IF (LUN.EQ.14) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+            IF (NEWSLIST) THEN
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	       ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	       BUFFERCOUNT=127,
+     &	       RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	       IOSTAT=IER,ORGANIZATION='INDEXED',SHARED)
+	    ELSE
+	       OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
+     &	       ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	       RECORDSIZE=NEWS_FOLDER_RECORD/4,
+     &	       IOSTAT=IER,ORGANIZATION='INDEXED',SHARED)
+            END IF
+
+	    IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	      IDUMMY = FILE_LOCK(IER,IER1)
+	      CALL CONVERT_BULLNEWS(BULLNEWS_FILE)
+	      NTRIES = 0
+	    END IF
+	    NTRIES = NTRIES + 1
+	    IF (NTRIES.GT.10) CALL ENABLE_CTRL_EXIT
+	   END DO
+	   IF (IER.EQ.0) NEWS_OPEN = .TRUE.
+	END IF
+
+	IF (LUN.EQ.8) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	    OPEN (UNIT=8,FILE='SYSUAF',DEFAULTFILE='SYS$SYSTEM:SYSUAF.DAT',
+     &       ACCESS='KEYED',FORM='UNFORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,IOSTAT=IER,SHARED,
+     &	     USEROPEN=LNM_MODE_EXEC)
+	   END DO
+	END IF
+
+	IF (LUN.EQ.9) THEN
+	   DO WHILE (FILE_LOCK(IER,IER1))
+	     OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='OLD',
+     &	      ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	      RECORDSIZE=FOLDER_MAX*2+3,
+     &	      IOSTAT=IER,ORGANIZATION='INDEXED',SHARED,
+     &	      KEY=(1:12:CHARACTER))
+	     IF (IER.EQ.FOR$IOS_INCRECLEN) THEN
+	       IDUMMY = FILE_LOCK(IER,IER1)	! Avoid breaking out of DO loop
+	       CALL CONVERT_INFFILE
+	       NTRIES = 0
+	     END IF
+	     NTRIES = NTRIES + 1
+	     IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
+	   END DO
+	END IF
+
+	IF (IER.EQ.FOR$IOS_FILNOTFOU.AND.LUN.NE.8) THEN
+	   CALL OPEN_FILE(LUN)
+	ELSE IF (IER.NE.0) THEN
+	   WRITE(6,'('' ERROR: Cannot open '',A)')
+     &			NAMES(NAME(LUN))(:TRIM(NAMES(NAME(LUN))))
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   IF (LUN.EQ.2.AND.REMOTE_SET.EQ.4) WRITE(6,'(1X,A)') 
+     &	      BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))
+	   WRITE(6,'(1X,A)') FOLDER_FILE(:TRIM(FOLDER_FILE)) 
+	   WRITE(6,'(1X,A)')USERNAME
+	   IF (IER1.EQ.0) THEN
+	      WRITE (6,'('' IOSTAT error = '',I)') IER
+	   ELSE
+	      CALL SYS_GETMSG(IER1)
+	   END IF
+	   CALL ENABLE_CTRL_EXIT
+	END IF
+
+	LUN = 0
+
+	RETURN
+	END
+
+
+	SUBROUTINE RESET_PROTECTION
+
+	IMPLICIT INTEGER (A-Z)
+
+	DATA PROT_LEVEL /0/
+
+	PROT_LEVEL = PROT_LEVEL - 1
+	IF (PROT_LEVEL.GT.0) RETURN
+
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
+
+	RETURN
+
+	ENTRY SET_PROTECTION
+
+	PROT_LEVEL = PROT_LEVEL + 1
+	IF (PROT_LEVEL.GT.1) RETURN
+
+	CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD,GROUP)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FOLDER_TO_NEWS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	NEWS_FOLDER = FOLDER
+	NEWS_FOLDER_NUMBER = FOLDER_NUMBER
+	NEWS_FOLDER_DESCRIP = FOLDER_DESCRIP(
+     &			       MIN(45,INDEX(FOLDER_DESCRIP,' ')):)
+	NEWS_F_NBULL = F_NBULL
+	NEWS_F_COUNT = F_COUNT
+	NEWS_F_START = F_START
+	NEWS_F_LAST = F_LAST
+	NEWS_F_NEWEST_BTIM(1) = F_NEWEST_BTIM(1)
+	NEWS_F_NEWEST_BTIM(2) = F_NEWEST_BTIM(2)
+	NEWS_F_FLAG = FOLDER_FLAG
+	NEWS_F_EXPIRE = FOLDER_BBEXPIRE
+ 	NEWS_F_EXPIRE_LIMIT = F_EXPIRE_LIMIT
+
+	RETURN
+
+	ENTRY FOLDER1_TO_NEWS
+
+	NEWS_FOLDER1 = FOLDER1
+	NEWS_FOLDER1_NUMBER = FOLDER1_NUMBER
+	NEWS_FOLDER1_DESCRIP = FOLDER1_DESCRIP(
+     &			       MIN(45,INDEX(FOLDER1_DESCRIP,' ')):)
+	NEWS_F1_NBULL = F1_NBULL
+	NEWS_F1_COUNT = F1_COUNT
+	NEWS_F1_START = F1_START
+	NEWS_F1_LAST = F1_LAST
+	NEWS_F1_NEWEST_BTIM(1) = F1_NEWEST_BTIM(1)
+	NEWS_F1_NEWEST_BTIM(2) = F1_NEWEST_BTIM(2)
+	NEWS_F1_FLAG = FOLDER1_FLAG
+	NEWS_F1_EXPIRE = FOLDER1_BBEXPIRE
+	NEWS_F1_EXPIRE_LIMIT = F1_EXPIRE_LIMIT
+
+	RETURN
+
+	ENTRY NEWS_TO_FOLDER
+
+	FOLDER = NEWS_FOLDER
+	FOLDER_NUMBER = NEWS_FOLDER_NUMBER
+	FOLDER_DESCRIP = NEWS_FOLDER(:MAX(1,TRIM(NEWS_FOLDER)))
+     &			 //NEWS_FOLDER_DESCRIP
+	FOLDER_BBOARD = '::'
+	F_NBULL = NEWS_F_NBULL
+	F_COUNT = NEWS_F_COUNT
+	F_START = NEWS_F_START
+	F_LAST = NEWS_F_LAST
+	F_NEWEST_BTIM(1) = NEWS_F_NEWEST_BTIM(1)
+	F_NEWEST_BTIM(2) = NEWS_F_NEWEST_BTIM(2)
+	FOLDER_FLAG = NEWS_F_FLAG
+	IF (BTEST(FOLDER_FLAG,8)) FOLDER_BBOARD = 'NONE'
+	FOLDER_BBEXPIRE = NEWS_F_EXPIRE
+	F_EXPIRE_LIMIT = NEWS_F_EXPIRE_LIMIT
+
+	RETURN
+
+	ENTRY NEWS_TO_FOLDER1
+
+	FOLDER1 = NEWS_FOLDER1
+	FOLDER1_NUMBER = NEWS_FOLDER1_NUMBER
+	FOLDER1_DESCRIP = NEWS_FOLDER1(:MAX(1,TRIM(NEWS_FOLDER1)))
+     &			 //NEWS_FOLDER1_DESCRIP
+	FOLDER1_BBOARD = '::'
+	F1_COUNT = NEWS_F1_COUNT
+	F1_NBULL = NEWS_F1_NBULL
+	F1_START = NEWS_F1_START
+	F1_LAST = NEWS_F1_LAST
+	F1_NEWEST_BTIM(1) = NEWS_F1_NEWEST_BTIM(1)
+	F1_NEWEST_BTIM(2) = NEWS_F1_NEWEST_BTIM(2)
+	FOLDER1_FLAG = NEWS_F1_FLAG
+	IF (BTEST(FOLDER1_FLAG,8)) FOLDER1_BBOARD = 'NONE'
+	FOLDER1_BBEXPIRE = NEWS_F1_EXPIRE
+	F1_EXPIRE_LIMIT = NEWS_F1_EXPIRE_LIMIT
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE CONVERT_BULLNEWSDIR
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($FORIOSDEF)'
+
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+  
+	CHARACTER*180 TEMP
+
+	CHARACTER BUFFER*12,DATETIME*24
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	CALL SET_PROTECTION
+
+	CALL OPEN_BULLNEWS
+
+	OPEN (UNIT=2,FILE=BULLNEWSDIR_FILE,
+     &	        STATUS='OLD',FORM='UNFORMATTED',
+     &	        RECORDTYPE='FIXED',RECORDSIZE=180/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        BUFFERCOUNT=127,KEY=(13:20:CHARACTER,
+     &	        1:8:CHARACTER,9:20:CHARACTER,21:84:CHARACTER,
+     &	        85:96:CHARACTER),ACCESS='KEYED')
+
+	IF (IER.NE.0) GO TO 900	! No BULLDIR file found.
+
+	IER1 = LIB$CREATE_DIR(
+     &		FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWSDIR]')
+	IF (.NOT.IER1) GO TO 900
+
+	NEW_FOLDER_NUMBER = 0
+
+	DO WHILE (IER.EQ.0)
+	   READ (2,IOSTAT=IER) TEMP
+	   IF (GET_INTEGER(%REF(TEMP)).NE.NEW_FOLDER_NUMBER) THEN
+	      IF (NEW_FOLDER_NUMBER.NE.0) CLOSE (UNIT=9,DISPOSE='KEEP')
+	      NEW_FOLDER_NUMBER = GET_INTEGER(%REF(TEMP))
+	      CALL SET_BULLNEWSDIR_FILE(NEW_FOLDER_NUMBER)
+              OPEN (UNIT=9,FILE=BULLNEWSDIR_FILE,
+     &	        STATUS='UNKNOWN',FORM='UNFORMATTED',SHARED,
+     &	        RECORDTYPE='FIXED',RECORDSIZE=NEWSDIR_RECORD_LENGTH/4,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	        BUFFERCOUNT=127,
+     &	        KEY=(1:4:INTEGER,5:12:CHARACTER,13:20:CHARACTER,
+     &	        57:64:CHARACTER),ACCESS='KEYED')
+	      IF (IER.NE.0) GO TO 900
+	   END IF
+	   NEWS_MSG_NUM = GET_INTEGER(%REF(TEMP(5:)))
+ 	   NEWS_MSG_BTIM_KEY = TEMP(13:)
+	   NEWS_EX_BTIM_KEY = TEMP(89:)
+	   NEWS_MSGID = TEMP(21:)
+ 	   CALL COPY2(MSG_BTIM,%REF(TEMP(97:)))
+	   CALL CONVERT_TO_GMT(MSG_BTIM)
+ 	   CALL GET_MSGKEY(MSG_BTIM,NEWS_POST_KEY)
+	   CALL LIB$MOVC3(76,%REF(TEMP(105:)),NEWS_BLOCK)
+
+	   WRITE (9,IOSTAT=IER1) NEWSDIR_ENTRY
+	END DO
+
+	CLOSE (UNIT=9,DISPOSE='KEEP')
+	CLOSE (UNIT=2)
+
+	CALL RESET_PROTECTION
+
+	BULLNEWSDIR_FILE = 'BULLNEWSDIR.DAT'
+	CALL ADD_DIRECTORY(BULLNEWSDIR_FILE)
+
+	IER = LIB$RENAME_FILE(BULLNEWSDIR_FILE(:TRIM(BULLNEWSDIR_FILE))
+     &		,'BULLNEWSDIR.OLD')
+
+	WRITE (6,'('' BULLNEWSDIR.DAT has been renamed to '',
+     &		'' BULLNEWSDIR.OLD and may now be deleted.'')')
+
+	RETURN
+
+900	CALL RESET_PROTECTION
+
+	CALL CLOSE_BULLNEWS
+
+	WRITE(6,'('' ERROR: Cannot convert BULLNEWSDIR.DAT'')')
+	IF (IER.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	IF (IER1.EQ.0) THEN
+	   WRITE (6,'('' IOSTAT error = '',I)') IER
+	ELSE
+	   CALL SYS_GETMSG(IER1)
+	END IF
+	CALL ENABLE_CTRL_EXIT
+
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLDIRS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER BUFFER*116
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	CALL SET_PROTECTION
+
+	OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',ACCESS='DIRECT',
+     &	      ORGANIZATION='RELATIVE',DISPOSE='KEEP',
+     &	      IOSTAT=IER)
+
+	IF (IER.NE.0) GO TO 900	! No BULLDIR file found.
+
+	READ (2'1,IOSTAT=IER1) BUFFER(:115)
+
+	CALL LIB$MOVC3(4,%REF(BUFFER(39:)),NBULL)
+
+	OPEN (UNIT=9,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED',
+     &	      INITIALSIZE=(((NBULL+1)*DIR_RECORD_LENGTH)/512)+5 )
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=9,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	END IF
+
+	IF (IER1.NE.0) GO TO 800
+
+	CALL SYS_BINTIM(BUFFER(:11)//' '//BUFFER(12:19),NEWEST_EXBTIM)
+	CALL SYS_BINTIM(BUFFER(20:30)//' '//BUFFER(31:38),NEWEST_MSGBTIM)
+	BULLDIR_HEADER(29:40) = BUFFER(39:)
+	CALL SYS_BINTIM(BUFFER(51:61)//' '//BUFFER(62:69),SHUTDOWN_BTIM)
+	BULLDIR_HEADER(49:52) = BUFFER(70:)
+	IF (IER.EQ.0) WRITE (9,IOSTAT=IER) BULLDIR_HEADER
+
+	ICOUNT = 2
+	DO WHILE (IER.EQ.0)
+	   READ (2'ICOUNT,IOSTAT=IER) BUFFER(:115)
+	   IF (IER.EQ.0) THEN
+	      MSG_NUM = ICOUNT - 1
+	      DESCRIP = BUFFER(:)
+	      FROM = BUFFER(54:)
+	      BULLDIR_ENTRY(81:84) = BUFFER(85:)
+	      BULLDIR_ENTRY(93:100) = BUFFER(108:)
+	      CALL SYS_BINTIM(BUFFER(89:99)//' '//BUFFER(100:107),EX_BTIM)
+	      CALL SYS_BINTIM(BUFFER(66:76)//' '//BUFFER(77:84),MSG_BTIM)
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      WRITE (9,IOSTAT=IER) BULLDIR_ENTRY
+	      ICOUNT = ICOUNT + 1
+	   END IF
+	END DO
+
+800	CLOSE (UNIT=9,DISPOSE='KEEP')
+	CLOSE (UNIT=2)
+
+900	CALL RESET_PROTECTION
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLFILES
+C
+C  SUBROUTINE CONVERT_BULLFILES
+C
+C  FUNCTION: Converts bulletin files to new format file.
+C	Add expiration time to directory file, add extra byte to bulletin
+C	file to show where each bulletin starts (for redunancy sake in
+C	case crash occurs).
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*81 BUFFER
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	OPEN (UNIT=9,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='OLD',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=107,ACCESS='DIRECT',
+     &	      ORGANIZATION='RELATIVE',DISPOSE='KEEP',FORM='FORMATTED',
+     &	      SHARED,READONLY,IOSTAT=IER)
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	OPEN (UNIT=10,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='OLD',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=80,
+     &	      FORM='FORMATTED',IOSTAT=IER,SHARED,READONLY)
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	CALL SET_PROTECTION
+
+	OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLFIL',STATUS='NEW',IOSTAT=IER,
+     &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=81,
+     &	      FORM='FORMATTED')
+
+	OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+
+	NEWEST_EXTIME = '00:00:00.00'
+	READ (9'1,1000,IOSTAT=IER) 
+     &		NEWEST_EXDATE,NEWEST_DATE,NEWEST_TIME(:8),
+     &		NBULL,NBLOCK,SHUTDOWN,SHUTDOWN_DATE,SHUTDOWN_TIME(:8)
+	NEMPTY = 0
+	IF (IER.EQ.0) CALL WRITEDIR(0,IER1)
+
+	EXTIME = '00:00:00.00'
+	ICOUNT = 2
+	DO WHILE (IER.EQ.0)
+	   READ(9'ICOUNT,1010,IOSTAT=IER)
+     &		DESCRIP,FROM,DATE,TIME(:8),LENGTH,EXDATE,SYSTEM,BLOCK
+	   IF (IER.EQ.0) THEN
+	      READ(10,'(A)') BUFFER
+	      WRITE(1,'(A)') BUFFER(:80)//CHAR(1)
+	      DO I=2,LENGTH
+	         READ(10,'(A)') BUFFER
+	         WRITE(1,'(A)') BUFFER
+	      END DO
+	      CALL WRITEDIR(ICOUNT-1,IER1)
+	      ICOUNT = ICOUNT + 1
+	   END IF
+	END DO
+
+	CLOSE (UNIT=9)
+	CLOSE (UNIT=2)
+	CLOSE (UNIT=10)
+	CLOSE (UNIT=1)
+
+	CALL RESET_PROTECTION
+	RETURN
+
+1000	FORMAT(A11,A11,A8,A4,A4,A4,A11,A8)
+1010	FORMAT(A53,A12,A11,A8,A4,A11,A4,A4)
+
+	END
+
+	SUBROUTINE CONVERT_BULLFILE
+C
+C  SUBROUTINE CONVERT_BULLFILE
+C
+C  FUNCTION: Converts bulletin data file to new format file.
+C
+C  NOTE: CONVERT_BULLFILES converts from 80 to 81 byte length.
+C	 This converts from 81 byte length to 128 compressed format.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*80 BUFFER,NEW_FILE
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	CALL CLOSE_BULLDIR
+
+	CALL SET_PROTECTION
+
+	CALL OPEN_BULLFOLDER
+
+100	READ (7,FMT=FOLDER_FMT,ERR=200)
+     &		FOLDER,FOLDER_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+
+	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//FOLDER(:TRIM(FOLDER))
+	NEW_FILE = FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFILOLD'
+	OPEN (UNIT=10,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL'
+     &	      ,STATUS='OLD',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=81,ACCESS='DIRECT',
+     &	      FORM='FORMATTED',IOSTAT=IER,SHARED,READONLY)
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	OPEN (UNIT=1,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	   //'.BULLFIL',STATUS='NEW',IOSTAT=IER,
+     &	   ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
+     &	   FORM='UNFORMATTED')
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &		//'.BULLFIL;-1',NEW_FILE)
+
+	CALL OPEN_BULLDIR
+
+	CALL READDIR(0,IER)
+
+	IF (IER.EQ.1) THEN
+	 NBLOCK = 0
+	 DO I=1,NBULL
+	   CALL READDIR(I,IER)
+	   NBLOCK = NBLOCK + 1
+	   SBLOCK = NBLOCK
+	   DO J=BLOCK,LENGTH+BLOCK-1
+	      READ(10'J,'(A)') BUFFER
+	      ILEN = TRIM(BUFFER)
+	      IF (ILEN.EQ.0) ILEN = 1
+	      CALL STORE_BULL(ILEN,BUFFER,NBLOCK)
+	   END DO
+	   CALL FLUSH_BULL(NBLOCK)
+	   LENGTH = NBLOCK - SBLOCK + 1
+	   BLOCK = SBLOCK
+	   CALL WRITEDIR(I,IER)
+	 END DO
+
+	 NEMPTY = 0
+	 CALL WRITEDIR(0,IER)
+	END IF
+
+	CLOSE (UNIT=10)
+	CLOSE (UNIT=1)
+
+	CALL CLOSE_BULLDIR
+	GOTO 100
+
+200	CALL OPEN_BULLDIR_SHARED
+
+	CALL RESET_PROTECTION
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLFOLDER(FILENAME)
+C
+C  SUBROUTINE CONVERT_BULLFOLDER
+C
+C  FUNCTION: Converts bulletin folder file to new format.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($FORIOSDEF)'
+
+	CHARACTER*(*) FILENAME
+
+	CHARACTER NEW_FILE*80,OLD_FOLDER*25
+
+	WRITE (6,'('' Converting '',A,'' to new format. Please wait.'')')
+     &			FILENAME(:TRIM(FILENAME))
+
+	CALL SET_PROTECTION
+
+	EODIR = MAX(INDEX(FILENAME,':'),INDEX(FILENAME,']'))
+	SUFFIX = INDEX(FILENAME(EODIR:),'.') + EODIR - 1
+	NEW_FILE = FILENAME(:SUFFIX)//'OLD'
+
+	DO WHILE (FILE_LOCK(IER,IER1))
+	   OPEN (UNIT=7,FILE=FILENAME,STATUS='OLD',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:25:CHARACTER,26:29:INTEGER))
+	END DO
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	INQUIRE(UNIT=7,RECORDSIZE=ASK_SIZE)
+
+	OPEN (UNIT=19,FILE=NEW_FILE,STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=FOLDER_RECORD,
+     &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER),
+     &		DISPOSE='DELETE')
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	IF (ASK_SIZE.EQ.184.OR.ASK_SIZE.EQ.173) THEN
+	 F_NUMBER = 0
+	 DO WHILE (IER.EQ.0)
+	   IF (ASK_SIZE.EQ.184) THEN
+	      READ (7,FMT='(A25,A4,A12,A80,A12,3A4,A8,5A4)',
+     &			KEYGE=F_NUMBER,KEYID=1,IOSTAT=IER)
+     &		OLD_FOLDER,F_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,FOLDER_SET
+	      CALL COPY2(F_NEWEST_NOSYS_BTIM,F_NEWEST_BTIM)
+	   ELSE IF (ASK_SIZE.EQ.173) THEN
+	      READ (7,FMT='(A25,A4,A12,A80,A12,3A4,A8,7A4)',
+     &			KEYGE=F_NUMBER,KEYID=1,IOSTAT=IER)
+     &		OLD_FOLDER,F_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,FOLDER_SET
+     &	        ,F_NEWEST_NOSYS_BTIM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      FOLDER = OLD_FOLDER
+	      CALL SYS_BINTIM('5-NOV-1982',NEWS_F_NEWEST_BTIM)
+              CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,FOLDER_CREATED_DATE)
+	      IF (NEWS_FEED()) THEN 
+		 CALL LIB$MOVC3(4,%REF(FOLDER_BBOARD(7:)),F_LAST)
+	      ELSE
+	         F_LAST = 0
+	      END IF
+	      WRITE (19,FMT=FOLDER_FMT,IOSTAT=IER)
+     &	        FOLDER,F_NUMBER,FOLDER_CREATED_DATE
+     &		,FOLDER_OWNER,FOLDER_DESCRIP
+     &	        ,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,FOLDER_SET
+     &		,F_NEWEST_NOSYS_BTIM,0,0,F_LAST
+	      F_NUMBER = F_NUMBER + 1
+	   END IF
+	 END DO
+	ELSE
+	 F_NUMBER = 0
+	 DO WHILE (IER.EQ.0)
+	   READ (7,FMT='(A25,A4,A12,A80,A12,3A4,A8)',
+     &			KEYGE=F_NUMBER,KEYID=1,IOSTAT=IER)
+     &		OLD_FOLDER,F_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
+     &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+	   IF (IER.EQ.0) THEN
+	      FOLDER_FLAG = 0
+	      IF (F_NUMBER.EQ.0) FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	      FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &		//OLD_FOLDER(:TRIM(OLD_FOLDER))
+	      CALL CHKACL
+     &		(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',IER)
+	      IF (IER.NE.(SS$_ACLEMPTY.OR.SS$_NORMAL).AND.IER) THEN
+		 FOLDER_FLAG = IBSET(FOLDER_FLAG,0)
+	      END IF
+	      DO WHILE (FILE_LOCK(IER,IER1))
+	       OPEN (UNIT=2,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	         //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
+     &	         RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	         ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	         KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	        IF (IER.EQ.FOR$IOS_INCFILORG) THEN
+	          IDUMMY = FILE_LOCK(IER,IER1)
+	          CALL CONVERT_BULLDIRS
+		END IF
+	      END DO
+	      IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
+		 F_NEWEST_BTIM(1) = 0
+		 F_NEWEST_BTIM(2) = 0
+	      ELSE
+	         CALL READDIR(0,IER)
+	         IF (NEWEST_DATE.EQ.'5-NOV-1956 ') THEN
+		    IF (NBULL.GT.0) THEN
+		       CALL READDIR(NBULL,IER)
+		       NEWEST_DATE = DATE
+		       NEWEST_TIME = TIME
+		       CALL WRITEDIR(0,IER)
+		    END IF
+	         END IF
+	         CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,F_NEWEST_BTIM)
+	         CLOSE (UNIT=2)
+	      END IF
+	      FOLDER = OLD_FOLDER
+              CALL SYS_BINTIM('5-NOV-1982',NEWS_F_NEWEST_BTIM)
+              CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,FOLDER_CREATED_DATE)
+              WRITE (19,FMT=FOLDER_FMT,IOSTAT=IER)
+     &          FOLDER,F_NUMBER,FOLDER_CREATED_DATE
+     &	       ,FOLDER_OWNER,FOLDER_DESCRIP
+     &	        ,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
+     &	        ,NBULL,F_NEWEST_BTIM,FOLDER_FLAG,0,F_NEWEST_BTIM,0,0,0
+	      F_NUMBER = F_NUMBER + 1
+	   END IF
+	 END DO
+	END IF
+
+	CLOSE (UNIT=7)
+	CLOSE (UNIT=19,STATUS='SAVE')
+
+	IER = LIB$RENAME_FILE(NEW_FILE,FILENAME)
+	IER = LIB$RENAME_FILE(BULLFOLDER_FILE//';-1',NEW_FILE)
+
+	CALL RESET_PROTECTION
+
+	IER = LIB$DELETE_FILE(BBOARD_DIRECTORY(:TRIM(BBOARD_DIRECTORY))
+     &		//'BOARD.COM;*')	! BULLETIN$ is referenced in old file
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_BULLNEWS(FILENAME)
+C
+C  SUBROUTINE CONVERT_BULLNEWS
+C
+C  FUNCTION: Converts bulletin NEWS file to new format.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($SSDEF)'
+
+	INCLUDE '($FORIOSDEF)'
+
+	CHARACTER*(*) FILENAME
+
+	CHARACTER NEW_FILE*80,OLD_FOLDER*25,OLD_DESCRIP*55,TMP*2     
+
+	WRITE (6,'('' Converting '',A,'' to new format. ''
+     &		,''This will take a while.'')') FILENAME(:TRIM(FILENAME))
+
+	CALL SET_PROTECTION
+
+	EODIR = MAX(INDEX(FILENAME,':'),INDEX(FILENAME,']'))
+	SUFFIX = INDEX(FILENAME(EODIR:),'.') + EODIR - 1
+	NEW_FILE = FILENAME(:SUFFIX)//'OLD'
+
+	DO WHILE (FILE_LOCK(IER,IER1))
+	   OPEN (UNIT=7,FILE=FILENAME,STATUS='OLD',
+     &	        RECORDTYPE='FIXED',ACCESS='KEYED',
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:25:CHARACTER,26:29:INTEGER))
+	END DO
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	OPEN (UNIT=19,FILE=NEW_FILE,STATUS='NEW',
+     &	        ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	        RECORDSIZE=NEWS_FOLDER_RECORD/4,INITIALSIZE=600,
+     &	        ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	        KEY=(1:44:CHARACTER,45:48:INTEGER,49:56:CHARACTER,
+     &		57:64:CHARACTER:DESCENDING),DISPOSE='DELETE')
+
+	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
+
+	NEWS_FOLDER_NUMBER = 0
+        CALL SYS_BINTIM('5-NOV-1982',NEWS_F_NEWEST_BTIM)
+        CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,NEWS_F_CREATED_DATE)
+        CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NEWS_F_NEWEST_BTIM)
+        CALL GET_MSGKEY(NEWS_F_NEWEST_BTIM,NEWS_F_EXPIRED_DATE)
+	NEWS_F_LAST = 0
+	NEWS_F_FLAG = 0
+	NEWS_F_EXPIRE = 7
+	NEWS_F_FIRST = 0
+	NEWS_F_END = 0
+	NEWS_F_EXPIRE_LIMIT = 0
+	READ (7,KEY=1000,KEYID=1,IOSTAT=IER) INPUT(:108)
+	DO WHILE (IER.EQ.0)
+	      OLD_FOLDER = INPUT(:25)
+	      CALL LIB$MOVC3(4,%REF(INPUT(26:)),NEWS_FOLDER_NUMBER)
+	      OLD_DESCRIP = INPUT(30:)
+	      CALL LIB$MOVC3(4,%REF(INPUT(87:)),NEWS_F_START)
+              CALL LIB$MOVC3(4,%REF(INPUT(91:)),NEWS_F_COUNT)
+              CALL LIB$MOVC3(4,%REF(INPUT(97:)),NEWS_F_NBULL)
+              CALL LIB$MOVC3(8,%REF(INPUT(101:)),NEWS_F_NEWEST_BTIM)
+	      LMOVE = INDEX(OLD_DESCRIP,' ')-1
+	      IF (LMOVE.LE.0) THEN
+	         NEWS_FOLDER = OLD_FOLDER
+	         NEWS_FOLDER_DESCRIP = OLD_DESCRIP
+	      ELSE
+	         NEWS_FOLDER = OLD_FOLDER//OLD_DESCRIP(:MIN(19,LMOVE))
+	         NEWS_FOLDER_DESCRIP = OLD_DESCRIP(MIN(20,LMOVE+1):)
+	      END IF
+  	      WRITE (19,IOSTAT=IER) NEWS_FOLDER_COM  
+	      READ (7,IOSTAT=IER) INPUT(:108)
+	 END DO
+
+	CLOSE (UNIT=7)
+	CLOSE (UNIT=19,STATUS='SAVE')
+
+	IER = LIB$RENAME_FILE(NEW_FILE,FILENAME)
+	IER = LIB$RENAME_FILE(BULLNEWS_FILE//';-1',NEW_FILE)
+
+	CALL RESET_PROTECTION
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_USERFILE
+C
+C  SUBROUTINE CONVERT_USERFILE
+C
+C  FUNCTION: Converts user file to new format which has 8 bytes added.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER BUFFER*74,NEW_FILE*80
+
+	CHARACTER*12 LOGIN_DATE,READ_DATE
+	CHARACTER*8 LOGIN_TIME,READ_TIME
+
+	WRITE (6,'('' Converting data files to new format. Please wait.'')')
+
+	EODIR = MAX(INDEX(BULLUSER_FILE,':'),INDEX(BULLUSER_FILE,']'))
+	SUFFIX = INDEX(BULLUSER_FILE(EODIR:),'.') + EODIR - 1
+	NEW_FILE = BULLUSER_FILE(:SUFFIX)//'OLD'
+	IER = LIB$RENAME_FILE(BULLUSER_FILE,NEW_FILE)
+
+	OPEN (UNIT=9,FILE=NEW_FILE,STATUS='OLD',
+     &	     ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	     FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	     KEY=(1:12:CHARACTER))
+	INQUIRE (UNIT=9,RECORDSIZE=RECL)
+
+	IF ((RECL-28)/16.GT.FLONG) THEN
+	   WRITE (6,'('' ERROR: Old data files have more folders'',
+     &		      '' than was specified with BULLUSER.INC.'')')
+	   WRITE (6,'('' Recompile with correct FOLDER_MAX.'')')
+	   IER = LIB$RENAME_FILE(NEW_FILE,BULLUSER_FILE)
+	   IF (USERNAME.EQ.'DECNET') THEN
+	      CALL SYS$DELPRC(,)
+	   ELSE
+	      CALL ENABLE_CTRL
+	      CALL SYS$CANEXH()
+	      CALL EXIT
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   CALL SET_PROTECTION
+	   OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='NEW',
+     &	    ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=28+FLONG*16,
+     &	    FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
+     &	    KEY=(1:12:CHARACTER))
+	END IF
+
+	IF (IER.NE.0) THEN
+	   WRITE (6,'('' Cannot convert user file.'')')
+	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	   CALL SYS_GETMSG(IER1)
+	   CALL RESET_PROTECTION
+	   CALL ENABLE_CTRL_EXIT
+	END IF
+
+	DO I=1,FLONG
+	   NEW_FLAG(I) = 'FFFFFFFF'X
+	   NOTIFY_FLAG(I) = 0
+	   BRIEF_FLAG(I) = 0
+	   SET_FLAG(I) = 0
+	END DO
+
+	IF (RECL.EQ.42.OR.RECL.EQ.50.OR.RECL.EQ.58.OR.RECL.EQ.66.OR.
+     &		RECL.EQ.74) THEN		! Old format
+	   IF (RECL.LE.58) RECL = 50
+	   IER = 0
+	   DO WHILE (IER.EQ.0)
+	      READ (9,'(A<RECL>)',IOSTAT=IER) BUFFER
+	      IF (IER.EQ.0) THEN
+		TEMP_USER = BUFFER(:12)
+	        LOGIN_DATE = BUFFER(13:23)
+	        LOGIN_TIME = BUFFER(24:31)
+	        READ_DATE = BUFFER(32:42)
+	        READ_TIME = BUFFER(43:50)
+	        IF (RECL.EQ.58)
+     &		  CALL LIB$MOVC3(8,%REF(BUFFER(51:)),SET_FLAG(1))
+	        IF (RECL.EQ.66)
+     &		  CALL LIB$MOVC3(8,%REF(BUFFER(59:)),NEW_FLAG(1))
+	        IF (RECL.EQ.74)
+     &		  CALL LIB$MOVC3(8,%REF(BUFFER(67:)),NOTIFY_FLAG(1))
+	        CALL SYS_BINTIM(LOGIN_DATE//' '//LOGIN_TIME,LOGIN_BTIM)
+	        CALL SYS_BINTIM(READ_DATE//' '//READ_TIME,READ_BTIM)
+	        WRITE (4,FMT=USER_FMT) TEMP_USER,LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	    END IF
+	   END DO
+	   IF (RECL.LT.66) THEN
+	     READ (4,KEY=USER_HEADER_KEY,FMT=USER_FMT) TEMP_USER,
+     &		LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	     NEW_FLAG(1) = PRV$M_OPER.OR.PRV$M_CMKRNL.OR.PRV$M_SETPRV
+	     WRITE (4,FMT=USER_FMT) TEMP_USER,LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	   END IF
+	ELSE					! Folder maxmimum increase
+	   OFLONG = (RECL - 28) / 16		! Old  #longwords/flag
+	   DO WHILE (IER.EQ.0)
+	    READ (9,FMT='(A12,<4+OFLONG*4>A4)',IOSTAT=IER) 
+     &	     TEMP_USER,LOGIN_BTIM,READ_BTIM,
+     &	     (NEW_FLAG(I),I=1,OFLONG),(SET_FLAG(I),I=1,OFLONG),
+     &	     (BRIEF_FLAG(I),I=1,OFLONG),(NOTIFY_FLAG(I),I=1,OFLONG)
+	    IF (IER.EQ.0) THEN
+	     WRITE (4,FMT=USER_FMT) TEMP_USER,LOGIN_BTIM,
+     &		READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	    END IF
+	   END DO
+	END IF
+
+	IER = 0
+
+	CLOSE (UNIT=9)
+	CLOSE (UNIT=4)
+
+	CALL RESET_PROTECTION
+
+	RETURN
+	END
+
+
+	SUBROUTINE READDIR(BULLETIN_NUM,ICOUNT)
+C
+C  SUBROUTINE READDIR
+C
+C  FUNCTION: Finds the entry for the specified bulletin in the
+C	directory file and returns the information for that entry.
+C
+C  INPUTS:
+C	BULLETIN_NUM  -  Bulletin number.  Starts with 1.
+C			 If 0, gives header info, i.e number of bulls,
+C			 number of blocks in bulletin file, etc.
+C  OUTPUTS:
+C	ICOUNT  -  The last record read by this routine.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /PROMPT/ COMMAND_PROMPT
+	CHARACTER*40 COMMAND_PROMPT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+	COMMON /NEXT/ NEXT
+
+	COMMON /KEEPLOCK/ KEEPLOCK
+	DATA KEEPLOCK/.FALSE./
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /BULLFIL/ BULLFIL
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+	COMMON /THREAD/ THREAD
+
+	CHARACTER*4 CFOLDER_NUMBER
+
+	ICOUNT = BULLETIN_NUM
+
+	IF (ICOUNT.EQ.0) THEN
+	   IF (.NOT.REMOTE_SET) THEN
+	      DO WHILE (REC_LOCK(IER))
+		IF (REMOTE_SET.EQ.4) THEN
+		   IER = 0
+		ELSE
+	           READ (2,KEYID=0,KEY=0,IOSTAT=IER) BULLDIR_HEADER
+		END IF
+	      END DO
+	      IF (IER.EQ.0) THEN
+		 CALL CONVERT_HEADER_FROMBIN
+		 IF (REMOTE_SET.EQ.4) THEN
+		    DIR_NUM = -1
+		 ELSE
+	            DIR_NUM = 0
+		 END IF
+	      END IF
+	   ELSE
+	      CALL REMOTE_GET_HEADER(BULLETIN_NUM,ICOUNT,IER)
+	      RETURN
+	   END IF
+	   IF (IER.EQ.0.AND..NOT.REMOTE_SET.EQ.4) THEN
+	      IF (NBULL.LT.0) THEN	! This indicates bulletin deletion
+					! was incomplete.
+		 CALL CLOSE_BULLDIR
+		 CALL OPEN_BULLDIR
+		 CALL CLEANUP_DIRFILE(1)
+		 CALL UPDATE_FOLDER
+	      END IF
+	      IF (NEMPTY.EQ.'    '.AND.
+     &		  FOLDER_BBOARD(:2).NE.'::') NEMPTY = 0
+C
+C  Check to see if cleanup of empty file space is necessary, which is
+C  defined here as being 50 blocks (200 128byte records).  Also check
+C  to see if cleanup was in progress but didn't properly finish.
+C
+	      IF (NEMPTY.GT.200.AND.TEST_BULLCP().EQ.0) THEN
+		 WRITE (CFOLDER_NUMBER,'(I4)') FOLDER_NUMBER
+	         IER1 = LIB$SPAWN('$'//COMMAND_PROMPT(:INDEX(
+     &		  COMMAND_PROMPT,'>')-1)//'/CLEANUP='//CFOLDER_NUMBER,
+     &		  'NL:','NL:',1,'BULL_CLEANUP')
+	      ELSE IF (NEMPTY.EQ.-1) THEN
+		 CALL CLEANUP_BULLFILE
+	      END IF
+	   END IF
+	ELSE
+	   IF (.NOT.REMOTE_SET) THEN
+	      DO WHILE (REC_LOCK(IER))
+		 IF (REMOTE_SET.EQ.4) THEN
+		    IF (NEXT) THEN
+		       IF (DIR_NUM.EQ.ICOUNT-1) THEN
+	                  READ(2,IOSTAT=IER) NEWSDIR_ENTRY
+	               ELSE
+	                  READ(2,KEYGE=ICOUNT
+     &			    ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY
+	               END IF
+		    ELSE
+		       IF (ICOUNT.LT.F_START) ICOUNT = F_START
+		       IF (ICOUNT.GT.F_NBULL) ICOUNT = F_NBULL
+	               IF (DIR_NUM.EQ.ICOUNT-1) THEN
+			  READ(2,IOSTAT=IER) NEWSDIR_ENTRY
+                       ELSE
+	                  READ(2,KEY=ICOUNT
+     &			    ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY
+			  IF (IER.NE.0.AND.ICOUNT.EQ.F_START) THEN
+	                     READ(2,KEYGT=ICOUNT
+     &			          ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY
+			     IF (IER.EQ.0) ICOUNT = NEWS_MSG_NUM
+			  END IF
+		       END IF
+		       IF (INCMD(:4).EQ.'BACK') THEN
+		          DO WHILE (IER.NE.0.AND.ICOUNT.GT.F_START)
+	                     ICOUNT = ICOUNT - 1
+			     READ(2,KEY=ICOUNT
+     &		                     ,KEYID=0,IOSTAT=IER) NEWSDIR_ENTRY 
+                          END DO
+		       END IF
+		    END IF
+		    IF (IER.EQ.0) THEN
+			  MSG_NUM = NEWS_MSG_NUM
+			  IF (MSG_NUM.GT.F_NBULL) THEN 
+			     IER = 36 
+			     UNLOCK 2
+                          ELSE IF (ICOUNT.LE.F_START.AND.
+     &				 MSG_NUM.GT.F_START) THEN
+			     INQUIRE (UNIT=7,OPENED=IER1)
+			     IF (.NOT.IER1) CALL OPEN_BULLNEWS_SHARED
+			     IDUMMY = REC_LOCK(IER)
+			     CALL READ_FOLDER_FILE_KEYNAME
+     &							(FOLDER,IER2)
+			     F_START = MSG_NUM
+		             CALL REWRITE_FOLDER_FILE(IER2)
+			     IF (.NOT.IER1) CALL CLOSE_BULLNEWS
+			     IDUMMY = REC_LOCK(IER)
+	                  END IF
+		       IF (IER.EQ.0.AND.MSG_NUM.NE.BULLETIN_NUM) THEN
+			  ICOUNT = MSG_NUM
+			  BULLETIN_NUM = ICOUNT
+		       END IF
+		    END IF
+		 ELSE
+                    IF (DIR_NUM.EQ.ICOUNT-1) THEN
+	               READ(2,IOSTAT=IER) BULLDIR_ENTRY
+		       IF (IER.EQ.0.AND.BLOCK.EQ.0) THEN
+			  REWRITE (2) BULLDIR_ENTRY(:65)//'   '//
+     &					BULLDIR_ENTRY(66:97)
+	                  READ(2,KEYID=0,KEY=ICOUNT,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		       END IF
+		       IF (MSG_NUM.NE.ICOUNT) THEN
+		          IER = 36
+		          UNLOCK 2 
+		       END IF
+		    ELSE
+	               READ(2,KEYID=0,KEY=ICOUNT,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		       IF (IER.EQ.0.AND.BLOCK.EQ.0) THEN
+			  REWRITE (2) BULLDIR_ENTRY(:65)//'   '//
+     &					BULLDIR_ENTRY(66:97)
+	                  READ(2,KEYID=0,KEY=ICOUNT,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		       END IF
+		    END IF
+		 END IF
+	      END DO
+	      IF (IER.EQ.0) THEN
+		 IF (REMOTE_SET.NE.4) CALL STR$UPCASE(FROM,FROM)
+	      	 CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+		 CALL CONVERT_ENTRY_FROMBIN
+		 DIR_NUM = MSG_NUM
+	         IF (REMOTE_SET.EQ.4.AND.BULLFIL.GT.0) CALL SET_BULLFIL
+	      ELSE
+		 DIR_NUM = -1
+	      END IF
+	   ELSE
+	      CALL REMOTE_GET_HEADER(BULLETIN_NUM,ICOUNT,IER)
+	   END IF
+	END IF
+
+	IF (IER.EQ.0) THEN
+	   IF (.NOT.REMOTE_SET) THEN
+	      ICOUNT = ICOUNT + 1
+	      IF (.NOT.KEEPLOCK) UNLOCK 2
+	   END IF
+	   IF (ICOUNT.GT.1.AND.BTEST(BULL_USER_CUSTOM,1)) THEN
+	      IF (BTEST(BULL_USER_CUSTOM,3)) THEN
+	         IF (.NOT.INCLUDE_MSG(FROM,DESCRIP)) ICOUNT = ICOUNT - 1
+	      ELSE IF (THREAD) THEN
+		 DUMMY = INCLUDE_MSG(FROM,DESCRIP)
+	      END IF
+       	   END IF
+	END IF
+
+	RETURN
+
+	END
+
+
+
+	INTEGER FUNCTION GET_INTEGER(NUM)
+
+        IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*4 CTEMP,INTEGER_KEY
+
+	CTEMP = INTEGER_KEY(NUM)
+
+	CALL LIB$MOVC3(4,%REF(CTEMP),GET_INTEGER)
+
+	RETURN
+	END
+
+
+
+	CHARACTER*4 FUNCTION INTEGER_KEY(NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER TEMP
+	CHARACTER*4 CTEMP
+	EQUIVALENCE (CTEMP,TEMP)
+
+	TEMP = NUM
+
+	DO I=4,1,-1
+	   INTEGER_KEY(I:I) = CTEMP(5-I:5-I)
+	END DO
+
+	RETURN
+	END
+
+
+	SUBROUTINE READDIR_KEYGE(IER)
+C
+C  SUBROUTINE READDIR_KEYGE
+C
+C  FUNCTION: Finds the entry for the specified bulletin in the
+C	directory file corresponding to or later than the date specified.
+C
+C  INPUTS:
+C	MSG_KEY	- Message key (passed via BULLDIR.INC common block).
+C  OUTPUTS:
+C	IER  -  If 0, no entry found.  Else contains message number.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+	COMMON /KEYID/ NEWS_KEYID
+	DATA NEWS_KEYID/1/
+
+	COMMON /KEEPLOCK/ KEEPLOCK
+
+	COMMON /BULLFIL/ BULLFIL
+
+	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM
+
+10	IF (.NOT.REMOTE_SET) THEN
+	   DO WHILE (REC_LOCK(IER))
+	      IF (REMOTE_SET.EQ.4) THEN
+	         IF (NEWS_KEYID.NE.2.OR.MSG_NUM.EQ.0) THEN
+		    READ(2,KEYGT=MSG_KEY
+     &		      ,KEYID=NEWS_KEYID,IOSTAT=IER) NEWSDIR_ENTRY
+                 ELSE
+		    READ(2,IOSTAT=IER) NEWSDIR_ENTRY
+	         END IF
+ 	         IF (IER.EQ.0) THEN
+		       MSG_NUM = NEWS_MSG_NUM
+		       IF (MSG_NUM.GT.F_NBULL) THEN
+			   IF (NEWS_KEYID.EQ.2.AND.MSG_NUM.NE.0) THEN 
+			     IF (MSG_NUM.GT.NEWS_F_END) THEN
+				IDUMMY = REC_LOCK(IER)
+			     END IF
+	                   ELSE
+		             IER = 36
+			     UNLOCK 2
+			   END IF
+	               END IF
+	         END IF
+	      ELSE
+	         READ(2,KEYID=1,KEYGT=MSG_KEY,IOSTAT=IER)
+     &					BULLDIR_ENTRY
+		 IF (IER.EQ.0.AND.BLOCK.EQ.0) THEN
+		    REWRITE (2) BULLDIR_ENTRY(:65)//'   '//
+     &					BULLDIR_ENTRY(66:97)
+	            READ(2,KEYID=0,KEY=MSG_NUM,IOSTAT=IER) 
+     &					BULLDIR_ENTRY
+		 END IF
+	      END IF
+	   END DO
+	   IF (IER.EQ.0) THEN
+	      IER = MSG_NUM
+	      CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	      CALL CONVERT_ENTRY_FROMBIN
+	      DIR_NUM = MSG_NUM
+	      IF (.NOT.KEEPLOCK) UNLOCK 2
+	      IF (REMOTE_SET.EQ.4.AND.BULLFIL.GT.0) CALL SET_BULLFIL
+	   ELSE
+	      IER = 0
+	      DIR_NUM = -1
+	   END IF
+	ELSE
+	   CALL REMOTE_GET_HEADER(DUMMY,-1,IER)
+ 	END IF
+
+	IF (IER.GT.0.AND.BTEST(BULL_USER_CUSTOM,1)) THEN
+	   IF (BTEST(BULL_USER_CUSTOM,3)) THEN
+	      IF (.NOT.INCLUDE_MSG(FROM,DESCRIP)) GO TO 10
+	   END IF
+       	END IF
+
+	RETURN
+
+	END
+
+
+
+	SUBROUTINE CONVERT_HEADER_FROMBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*24 DATETIME
+
+	IF (REMOTE_SET.EQ.4) THEN
+ 	   CALL COPY2(NEWEST_MSGBTIM,NEWS_F_NEWEST_BTIM)
+	   CALL GET_MSGKEY(%REF(NEWS_F_EXPIRED_DATE),%DESCR(NEWEST_EXBTIM))
+           NBULL = F_NBULL
+	   NEMPTY = 0
+	END IF
+
+	CALL SYS$ASCTIM(,DATETIME,NEWEST_EXBTIM,)
+
+	NEWEST_EXDATE = DATETIME(:11)
+	NEWEST_EXTIME = DATETIME(13:23)
+
+	CALL SYS$ASCTIM(,DATETIME,NEWEST_MSGBTIM,)
+
+	NEWEST_DATE = DATETIME(:11)
+	NEWEST_TIME = DATETIME(13:23)
+
+	CALL SYS$ASCTIM(,DATETIME,SHUTDOWN_BTIM,)
+
+	SHUTDOWN_DATE = DATETIME(:11)
+	SHUTDOWN_TIME = DATETIME(13:23)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_ENTRY_FROMBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /POST/ POSTTIME
+
+	CHARACTER*24 DATETIME
+
+	IF (REMOTE_SET.EQ.4) THEN
+ 	   CALL GET_MSGKEY(%REF(NEWS_MSG_BTIM_KEY),%DESCR(MSG_BTIM))
+ 	   CALL GET_MSGKEY(%REF(NEWS_EX_BTIM_KEY),%DESCR(EX_BTIM))
+	   IF (POSTTIME) THEN
+	      CALL GET_MSGKEY(%REF(NEWS_POST_KEY),%DESCR(MSG_BTIM))
+	      CALL CONVERT_FROM_GMT(MSG_BTIM)	! Assume stored is GMT
+	   END IF
+           DESCRIP = NEWS_DESCRIP
+           FROM = NEWS_FROM  
+           BLOCK = NEWS_BLOCK
+	   LENGTH = NEWS_LENGTH
+	   SYSTEM = 0
+	END IF
+
+	ENTRY CONVERT_ENTRY_FROMBIN_FOLDER 
+
+	CALL SYS$ASCTIM(,DATETIME,EX_BTIM,)
+
+	EXDATE = DATETIME(:11)
+	EXTIME = DATETIME(13:23)
+
+	CALL SYS$ASCTIM(,DATETIME,MSG_BTIM,)
+
+	DATE = DATETIME(:11)
+	TIME = DATETIME(13:23)
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE WRITEDIR(BULLETIN_NUM,IER)
+C
+C  SUBROUTINE WRITEDIR
+C
+C  FUNCTION: Writes the entry for the specified bulletin in the
+C	directory file.
+C
+C  INPUTS:
+C	BULLETIN_NUM  -  Bulletin number.  Starts with 1.
+C			 If 0, write the header of the directory file.
+C  OUTPUTS:
+C	IER - Error status from WRITE.
+C
+
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /DIR_POSITION/ DIR_NUM
+
+	CONV = .TRUE.
+
+	GO TO 10
+
+	ENTRY WRITEDIR_NOCONV(BULLETIN_NUM,IER)
+
+	CONV = .FALSE.
+	
+10	IF (BULLETIN_NUM.EQ.0) THEN
+	   IF (CONV) CALL CONVERT_HEADER_TOBIN
+	   IF (REMOTE_SET) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER)9,0,BULLDIR_HEADER
+	   ELSE
+	      IER = -1
+	      IF (DIR_NUM.EQ.0) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+                    IER = 0
+		 ELSE
+	            REWRITE (2,IOSTAT=IER) BULLDIR_HEADER
+		 END IF
+	      END IF
+	      IF (IER.NE.0) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+		    IER = 0
+		 ELSE
+		    READ (2,KEYID=0,KEY=0,IOSTAT=IER)
+		    IF (IER.EQ.0) THEN 
+	               REWRITE (2,IOSTAT=IER) BULLDIR_HEADER
+		    END IF
+		 END IF
+	      END IF
+	      IF (IER.NE.0) THEN
+		 IF (REMOTE_SET.NE.4) THEN
+	            WRITE (2,IOSTAT=IER) BULLDIR_HEADER
+		 END IF
+	      END IF
+	   END IF
+	ELSE
+	   MSG_NUM = BULLETIN_NUM
+	   IF (CONV) CALL CONVERT_ENTRY_TOBIN
+	   IF (REMOTE_SET) THEN
+	      WRITE(REMOTE_UNIT,'(3A)',IOSTAT=IER)9,BULLETIN_NUM,
+     &							BULLDIR_ENTRY
+	   ELSE
+	      IER = -1
+	      IF (DIR_NUM.EQ.MSG_NUM) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+	            REWRITE (2,IOSTAT=IER) NEWSDIR_ENTRY
+		 ELSE
+	            REWRITE (2,IOSTAT=IER) BULLDIR_ENTRY
+		 END IF
+	      END IF
+	      IF (IER.NE.0) THEN
+		 IF (REMOTE_SET.EQ.4) THEN
+		    IF (BULLETIN_NUM.NE.NEWS_F_END+1) THEN
+		       DO WHILE (REC_LOCK(IER))
+	                  READ (2,KEYID=0,KEY=BULLETIN_NUM,IOSTAT=IER)
+		       END DO
+		    END IF
+		 ELSE
+	            READ (2,KEYID=0,KEY=BULLETIN_NUM,IOSTAT=IER)
+		 END IF
+		 IF (REMOTE_SET.EQ.4.AND.
+     &			BULLETIN_NUM.EQ.NEWS_F_END+1) THEN
+                    CALL SPECIAL_NEWSDIR_ENTRY(IER)
+	         ELSE IF (IER.EQ.0) THEN
+		    IF (REMOTE_SET.EQ.4) THEN
+	               REWRITE (2,IOSTAT=IER) NEWSDIR_ENTRY
+		    ELSE
+	               REWRITE (2,IOSTAT=IER) BULLDIR_ENTRY
+		    END IF
+	         ELSE
+		    IF (REMOTE_SET.EQ.4) THEN
+	               WRITE (2,IOSTAT=IER) NEWSDIR_ENTRY
+		    ELSE
+	               WRITE (2,IOSTAT=IER) BULLDIR_ENTRY
+		    END IF
+		 END IF
+	      END IF
+	   END IF
+	END IF
+
+	IF (REMOTE_SET.AND.IER.GT.0) CALL ERROR_AND_EXIT
+
+	DIR_NUM = -1
+
+	RETURN
+
+	END
+
+
+
+        SUBROUTINE SPECIAL_NEWSDIR_ENTRY(IER)
+
+        IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLDIR.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($RMSDEF)'
+
+	CHARACTER*140 TEMP
+
+	DIMENSION BTIM(2)
+
+        READ (2,KEYID=3,KEY=NEWS_POST_KEY,IOSTAT=IER) TEMP
+	DO WHILE (IER.EQ.0.AND.NEWS_POST_KEY.EQ.TEMP(57:64))
+	   IF (NEWS_MSGID.EQ.TEMP(21:56)) THEN  
+	      IER = 2
+	      RETURN
+	   END IF
+           READ (2,IOSTAT=IER) TEMP
+	END DO
+
+10	IER1 = 0
+	DO WHILE (REC_LOCK(IER1))
+	   READ (2,KEYID=0,KEYGT=NEWS_F_END,
+     &			IOSTAT=IER1) INPUT(:NEWSDIR_RECORD_LENGTH)
+	END DO		
+	DO WHILE (IER1.EQ.0)
+	   CALL LIB$MOVC3(4,%REF(INPUT),FNUM)
+	   CALL GET_MSGKEY(%REF(INPUT(13:)),%DESCR(BTIM))
+	   IF (COMPARE_BTIM(BTIM,NEWEST_EXBTIM).LT.0.AND.
+     &		  .NOT.BTEST(FOLDER_FLAG,13)) THEN
+	      CALL COPY2(NEWEST_EXBTIM,BTIM)
+	   END IF
+	   F_COUNT = F_COUNT + 1
+	   CALL LIB$MOVC3(4,%REF(INPUT),NEWS_F_END)
+	   DO WHILE (REC_LOCK(IER1))
+	      READ (2,IOSTAT=IER1) INPUT(:NEWSDIR_RECORD_LENGTH)
+	   END DO		
+	END DO
+
+	IF (MSG_NUM.NE.NEWS_F_END+1) THEN
+	   MSG_NUM = NEWS_F_END + 1
+	   CALL CONVERT_ENTRY_TOBIN
+	END IF
+	WRITE (2,IOSTAT=IER) NEWSDIR_ENTRY  
+
+	IF (IER.NE.0) THEN
+	   CALL ERRSNS(IDUMMY,IER1)
+           IF (IER1.EQ.RMS$_DUP) GO TO 10
+	ELSE
+	   F_COUNT = F_COUNT + 1
+	END IF	
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_HEADER_TOBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFOLDER.INC' 
+
+	INCLUDE 'BULLDIR.INC'
+
+        COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CALL SYS_BINTIM(NEWEST_EXDATE//' '//NEWEST_EXTIME,NEWEST_EXBTIM)
+
+	CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,NEWEST_MSGBTIM)
+
+	CALL SYS_BINTIM(SHUTDOWN_DATE//' '//SHUTDOWN_TIME,SHUTDOWN_BTIM)
+
+	IF (REMOTE_SET.EQ.4) THEN
+ 	   CALL COPY2(NEWS_F_NEWEST_BTIM,NEWEST_MSGBTIM)
+           CALL GET_MSGKEY(NEWEST_EXBTIM,NEWS_F_EXPIRED_DATE)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONVERT_ENTRY_TOBIN
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+        COMMON /LOCALPOST/ LOCAL_POST
+
+	CALL SYS_BINTIM(EXDATE//' '//EXTIME,EX_BTIM)
+
+        IF (REMOTE_SET.EQ.4) THEN
+	   CALL CONVERT_TO_GMT(MSG_BTIM)
+	   CALL GET_MSGKEY(MSG_BTIM,NEWS_POST_KEY)
+       	   CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,MSG_BTIM)
+	ELSE
+       	   CALL SYS_BINTIM(DATE//' '//TIME,MSG_BTIM)
+        END IF
+
+	IF (LOCAL_POST) THEN
+	   CALL SYS_BINTIM(DATE//' '//TIME
+     &			   (:TRIM(TIME)-2)//'00',MSG_BTIM)
+	   CALL GET_MSGKEY(MSG_BTIM,NEWS_POST_KEY)
+	END IF
+
+	IF (REMOTE_SET.EQ.4) THEN
+           NEWS_DESCRIP = DESCRIP
+           NEWS_FROM = FROM
+           NEWS_BLOCK = BLOCK
+           NEWS_LENGTH = LENGTH
+           NEWS_MSG_NUM = MSG_NUM
+	   CALL GET_MSGKEY(MSG_BTIM,NEWS_MSG_BTIM_KEY)
+	   CALL GET_MSGKEY(EX_BTIM,NEWS_EX_BTIM_KEY)
+	ELSE
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_FIRST_EXPIRED(NDEL)
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLDIR.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+ 
+        COMMON /KEYID/ NEWS_KEYID
+
+	COMMON /KEEPLOCK/ KEEPLOCK
+ 
+	EX_BTIM(1) = 0
+	EX_BTIM(2) = 0	
+	MSG_NUM = 0
+
+	ENTRY READ_NEXT_EXPIRED(NDEL) 	
+
+	NEWS_KEYID = 2
+	KEEPLOCK = .TRUE.
+      	CALL GET_MSGKEY(EX_BTIM,MSG_KEY)
+	CALL READDIR_KEYGE(NDEL)
+	KEEPLOCK = .FALSE.
+	NEWS_KEYID = 1
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READACL(FILENAME,ACLENT,ACLLENGTH)
+C
+C  SUBROUTINE READACL
+C
+C  FUNCTION: Reads the ACL of a file.
+C
+C  PARAMETERS:
+C	FILENAME - Name of file to check.
+C	ACLENT - String which will be large enough to hold ACL information.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER ACLENT*(*),OUTPUT*80,ACLSTR*256,FILENAME*(*)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_READACL,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST),,,)
+
+	BIG = .NOT.IER
+	IF (BIG) THEN
+	   IER = SYS$PARSE_ACL('(ID=*,ACCESS=NONE)',ACLENT,,)
+	   ACLLENGTH = ACL$S_ADDACLENT
+	   CTXT = 0
+	END IF
+
+	DO ACC_TYPE=1,2
+	 POINT = 1
+	 OUTLEN = 0
+	 DO WHILE ((POINT.LT.ACLLENGTH).AND.IER)
+	   IF (.NOT.BIG) THEN
+	      IER = SYS$FORMAT_ACL(ACLENT(POINT:POINT-1+
+     &		ICHAR(ACLENT(POINT:POINT))),ACLLEN,ACLSTR,,,,)
+	   ELSE
+	      CALL INIT_ITMLST	! Initialize item list
+	      CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_FNDACETYP,%LOC(ACLENT))
+	      CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	      IER = SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST)
+     &				,,,CTXT,,)
+	      IER = SYS$FORMAT_ACL(ACLENT(:ICHAR(ACLENT(:1))),
+     &				ACLLEN,ACLSTR,,,,)
+	      CALL LIB$MOVC3(4,%REF(ACLENT(5:)),ACCESS)
+	      IF (ACCESS.EQ.0) IER = .FALSE.
+	   END IF
+	   AC = INDEX(ACLSTR,',ACCESS')
+	   IF ((ACC_TYPE.EQ.1.AND.INDEX(ACLSTR(AC:),'WRITE').GT.0).OR.
+     &	       (ACC_TYPE.EQ.2.AND.INDEX(ACLSTR(AC:),'READ').GT.0.AND.
+     &	        INDEX(ACLSTR(AC:),'WRITE').EQ.0)) THEN
+	      START_ID = INDEX(ACLSTR,'=') + 1
+	      END_ID = INDEX(ACLSTR,',ACCESS') - 1
+	      IF (ACLSTR(END_ID:END_ID).EQ.']') THEN
+		 START_ID = END_ID - 1
+		 ASCII = .FALSE.
+		 DO WHILE (ACLSTR(START_ID:START_ID).NE.'['.AND.
+     &			   ACLSTR(START_ID:START_ID).NE.'='.AND.
+     &			   (ACLSTR(START_ID:START_ID).NE.','.OR..NOT.ASCII))
+		    IF (ACLSTR(START_ID:START_ID).NE.','.AND.
+     &			(ACLSTR(START_ID:START_ID).LT.'0'.OR.
+     &			 ACLSTR(START_ID:START_ID).GT.'9')) ASCII = .TRUE.
+		    IF (ACLSTR(START_ID:START_ID).NE.','.OR..NOT.ASCII) THEN
+		       START_ID = START_ID - 1
+	 	    END IF
+		 END DO
+		 IF (ASCII) THEN
+		    START_ID = START_ID + 1
+		    END_ID = END_ID - 1
+		    IF (ACLSTR(START_ID:START_ID).EQ.'*') THEN
+		       START_ID = INDEX(ACLSTR,'=') + 1
+	               END_ID = INDEX(ACLSTR,'ACCESS') - 2
+		    END IF
+		 END IF
+	      END IF
+	      IF (OUTLEN.EQ.0) THEN
+		IF (FILENAME.NE.BULLUSER_FILE) THEN
+	         IF (ACC_TYPE.EQ.1) THEN
+		    WRITE (6,'(
+     &		    '' These users can read and write to this folder:'')')
+	         ELSE
+		    WRITE (6,'(
+     &		    '' These users can only read this folder:'')')
+	         END IF
+		ELSE
+		 WRITE (6,'('' The following are rights identifiers'',
+     &			'' which will give privileges.'')')
+		END IF
+		OUTLEN = 1
+	      END IF
+	      IDLEN = END_ID - START_ID + 1
+	      IF (OUTLEN+IDLEN-1.GT.80) THEN
+		 WRITE (6,'(1X,A)') OUTPUT(:OUTLEN-1)
+		 OUTPUT = ACLSTR(START_ID:END_ID)//','
+		 OUTLEN = IDLEN + 2
+	      ELSE IF (OUTLEN+IDLEN-1.EQ.80) THEN
+		 WRITE (6,'(1X,A)') 
+     &			OUTPUT(:OUTLEN-1)//ACLSTR(START_ID:END_ID)
+	         OUTLEN = 1
+	      ELSE
+	         OUTPUT(OUTLEN:) = ACLSTR(START_ID:END_ID)//','
+		 OUTLEN = OUTLEN + IDLEN + 1
+	      END IF
+	   END IF
+	   POINT = POINT + ICHAR(ACLENT(POINT:POINT))
+	 END DO
+	 IF (OUTLEN.GT.1) WRITE (6,'(1X,A)') OUTPUT(:OUTLEN-2)
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CONVERT_INFFILE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	OPEN (UNIT=10,FILE=BULLINF_FILE,STATUS='OLD',
+     &	   ACCESS='KEYED',RECORDTYPE='FIXED',
+     &	   IOSTAT=IER,ORGANIZATION='INDEXED',
+     &	   KEY=(1:12:CHARACTER))
+
+	INQUIRE (UNIT=10,RECORDSIZE=RECL)
+
+	IF ((RECL-3)/2.GT.FOLDER_MAX) THEN
+	   WRITE (6,'('' ERROR: Old data files have more folders'',
+     &		      '' than was specified with BULLUSER.INC.'')')
+	   WRITE (6,'('' Recompile with correct FOLDER_MAX.'')')
+	   IF (USERNAME.EQ.'DECNET') THEN
+	      CALL SYS$DELPRC(,)
+	   ELSE
+	      CALL ENABLE_CTRL
+	      CALL SYS$CANEXH()
+	      CALL EXIT
+	   END IF
+	END IF
+
+	RECL = (RECL-3)/2
+
+	OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='NEW',
+     &	   ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=FOLDER_MAX*2+3,
+     &	   IOSTAT=IER,ORGANIZATION='INDEXED',
+     &	   KEY=(1:12:CHARACTER))
+
+	DO WHILE (IER.EQ.0)
+	 READ (10,IOSTAT=IER) TEMP_USER,((LAST_READ_BTIM(J,I),J=1,2),I=1,RECL)
+	 IF (IER.EQ.0) WRITE (9) TEMP_USER,
+     &			((LAST_READ_BTIM(J,I),J=1,2),I=1,FOLDER_MAX)
+	END DO
+
+	CLOSE (UNIT=10,STATUS='DELETE')
+
+	CLOSE (UNIT=9)
+
+	RETURN
+	END
+
+
+	SUBROUTINE ERROR_AND_EXIT
+
+	IMPLICIT INTEGER (A-Z)
+	
+	CALL ERRSNS(IDUMMY,IER)
+	CALL SYS_GETMSG(IER)
+	CALL ENABLE_CTRL_EXIT
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE COPY_ACL(INFILE,OUTFILE)
+C
+C  SUBROUTINE COPY_ACL
+C
+C  FUNCTION:
+C	Copy ACLs from one file to another file
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER*(*) INFILE,OUTFILE
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,ACL$C_ACLLENGTH,%LOC(ACLLENGTH))
+				! Get length needed to store acl output
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST),,,,,)
+
+	CALL LIB$GET_VM(ACLLENGTH+12,ACLSTR)	! Create character string to
+	CALL MAKE_CHAR(%VAL(ACLSTR),ACLLENGTH,ACLLENGTH)	! store acl
+
+	CALL COPY_ACL1(INFILE,OUTFILE,%VAL(ACLSTR),ACLLENGTH)
+						! Pass location of string
+	CALL LIB$FREE_VM(ACLLENGTH+12,ACLSTR)
+
+	RETURN
+	END
+
+
+	SUBROUTINE COPY_ACL1(INFILE,OUTFILE,ACLENT,ACLLENGTH)
+C
+C  SUBROUTINE COPY_ACL1
+C
+C  FUNCTION: Called by COPY_ACL to actually do the copy.  Need 2 routines
+C	since must convert location of string into a character string.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($ACLDEF)'
+
+	CHARACTER ACLENT*(*),INFILE*(*),OUTFILE*(*)
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_READACL,%LOC(ACLENT))
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST),,,,,)
+				! Read input file acl
+
+	IF (.NOT.IER) THEN
+	   IER = SYS$PARSE_ACL('(ID=*,ACCESS=NONE)',ACLENT,,)
+	   IF (.NOT.IER) RETURN
+	   ACLLENGTH = ACL$S_ADDACLENT
+	   CTXT = 0
+	   DO WHILE (IER)
+	      CALL INIT_ITMLST	! Initialize item list
+	      CALL ADD_2_ITMLST(ICHAR(ACLENT(:1)),ACL$C_ADDACLENT,
+     &				%LOC(ACLENT))
+	      CALL END_ITMLST(ACL1_ITMLST)	! Get address of itemlist
+	      IER = SYS$CHANGE_ACL
+     &			(,ACL$C_FILE,OUTFILE,%VAL(ACL1_ITMLST),,,)
+
+	      CALL INIT_ITMLST	! Initialize item list
+	      CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_FNDACETYP,%LOC(ACLENT))
+	      CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	      IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST)
+     &				,,,CTXT,,)
+	      CALL LIB$MOVC3(4,%REF(ACLENT(5:)),ACCESS)
+	      IF (ACCESS.EQ.0) RETURN		! ID=*, ACCESS=NONE, which has
+						! (and must) be applied first
+	   END DO
+	   RETURN
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+
+	POINT = 1
+	DO WHILE (POINT.LT.ACLLENGTH)	! Transfer all acls to output file
+	   CALL ADD_2_ITMLST(ICHAR(ACLENT(POINT:POINT)),ACL$C_ADDACLENT,
+     &		%LOC(ACLENT(POINT:)))
+	   POINT = POINT + ICHAR(ACLENT(POINT:POINT))
+	END DO
+
+	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
+	IER = SYS$CHANGE_ACL(,ACL$C_FILE,OUTFILE,%VAL(ACL_ITMLST),,,)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CHECK_DIR_ACCESS()
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*80 TEST,TEST1
+
+	DATA CHECKED /.FALSE./
+
+  	IF (CHECKED) RETURN
+
+	CHECKED = .TRUE.
+
+	IF (SYS_TRNLNM_SYSTEM(FOLDER_DIRECTORY,TEST)) THEN 
+	   IER = SYS_TRNLNM(FOLDER_DIRECTORY,TEST1)
+	   IF (IER) IER = TEST.NE.TEST1
+	   IF (IER) THEN 
+	      TEST1 = BULLNEWS_FILE
+	      CALL ADD_DIRECTORY(BULLNEWS_FILE)
+	      C = 0
+	      IER = LIB$FIND_FILE(BULLNEWS_FILE,BULLNEWS_FILE,C)
+	      BULLNEWS_FILE = TEST1
+	   END IF
+	   IF (.NOT.IER) THEN  
+	      TEST1 = FOLDER_DIRECTORY
+	      FOLDER_DIRECTORY = TEST
+	   END IF
+	   CALL ADD_DIRECTORY(BULLNEWS_FILE)
+	   IF (.NOT.IER) FOLDER_DIRECTORY = TEST1
+	ELSE
+	   CALL ADD_DIRECTORY(BULLNEWS_FILE)
+	END IF
+
+	CALL CHECK_DIR(FOLDER_DIRECTORY,.FALSE.)
+	CALL CHECK_DIR(NEWS_DIRECTORY,.FALSE.)
+
+	CALL ADD_DIRECTORIES
+
+        RETURN
+        END
+ 
+
+
+	SUBROUTINE ADD_DIRECTORIES
+
+        INCLUDE 'BULLFILES.INC'
+
+	CALL ADD_DIRECTORY(BULLUSER_FILE)
+	CALL ADD_DIRECTORY(BULLFOLDER_FILE)
+	CALL ADD_DIRECTORY(BULLINF_FILE)
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION CHECK_DIR(DIRECTORY,LIBRARY)
+
+	IMPLICIT INTEGER (A-Z)
+
+        INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*(*) DIRECTORY
+
+	CHARACTER*80 TEST,TEST1
+
+	CHECK_DIR = PRESENT(BULLUSER_FILE,DIRECTORY,TEST).AND.
+     &		    PRESENT(BULLFOLDER_FILE,DIRECTORY,TEST).AND.
+     &		    PRESENT(BULLINF_FILE,DIRECTORY,TEST)
+
+	IF (CHECK_DIR) THEN
+	   IF (SYS_TRNLNM(DIRECTORY,TEST)) DIRECTORY = TEST
+	   RETURN
+	END IF
+
+	TEST = ' '
+
+	IF (INDEX(DIRECTORY,']').EQ.0) THEN
+	   CALL SYS_TRNLNM(DIRECTORY,TEST1)
+	ELSE
+	   TEST1 = DIRECTORY
+	END IF
+
+	IER = 1
+	DO WHILE (TEST.NE.TEST1.AND.IER)
+	   IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',TEST)
+	END DO
+
+	IF (.NOT.LIBRARY.AND.TEST.EQ.' ') THEN
+	   IER = SYS_TRNLNM_SYSTEM(DIRECTORY,TEST)
+	   IF (.NOT.IER.AND.TEST1.EQ.DIRECTORY) RETURN
+	END IF
+
+	IF (TEST.NE.TEST1) THEN
+	   IF (LIBRARY) THEN
+	      WRITE (6,'('' ERROR: Not a valid library. '')')
+	      RETURN
+	   END IF
+           IF (INDEX(TEST1,':').EQ.0) TEST1 = TEST1(:TRIM(TEST1))//':'
+	   CALL DISABLE_PRIVS
+	   OPEN(UNIT=3,FILE=TEST1(:TRIM(TEST1))//
+     &		'BULL.SCR',STATUS='NEW',IOSTAT=IER)
+	   CLOSE(UNIT=3,STATUS='DELETE')
+	   CALL ENABLE_PRIVS
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR: No access to directory: '',A)')
+     &		TEST1(:TRIM(TEST1))
+	      CALL EXIT
+	   END IF
+	   DIRECTORY = TEST1
+	ELSE
+           IF (INDEX(TEST,':').EQ.0) TEST = TEST(:TRIM(TEST))//':'
+	   DIRECTORY = TEST
+    	   DO WHILE (IER)
+	      IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',TEST)
+	   END DO
+	   CHECK_DIR = .TRUE.
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	LOGICAL FUNCTION PRESENT(FILE,DIR,TEST)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) FILE,DIR,TEST
+
+	FILE = FILE(INDEX(FILE,':')+1:)
+	FILE = FILE(INDEX(FILE,']')+1:)
+        IF (INDEX(DIR,':').EQ.0.AND.INDEX(DIR,'[').EQ.0.AND.
+     &	    INDEX(DIR,'<').EQ.0) DIR = DIR(:TRIM(DIR))//':'
+	C = 0
+	PRESENT = LIB$FIND_FILE(DIR(:TRIM(DIR))//FILE,TEST,C)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE ADD_DIRECTORY(DIRECTORY)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*(*) DIRECTORY
+
+	DIRECTORY = DIRECTORY(INDEX(DIRECTORY,':')+1:)
+	DIRECTORY = DIRECTORY(INDEX(DIRECTORY,']')+1:)
+        IF (INDEX(FOLDER_DIRECTORY,':').EQ.0) FOLDER_DIRECTORY 
+     &			= FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//':'
+	DIRECTORY = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &			//DIRECTORY
+
+	RETURN
+        END
+
+
+
+	SUBROUTINE SET_LIBRARY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+        INCLUDE 'BULLFOLDER.INC'
+ 
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+        CALL CLI$GET_VALUE('LIBRARY',BULL_PARAMETER,LEN_P)
+
+	IF (CHECK_DIR(BULL_PARAMETER,.TRUE.)) THEN
+	   FOLDER_DIRECTORY = BULL_PARAMETER
+	   CALL ADD_DIRECTORIES
+	   FOLDER_SET = .FALSE.
+           FOLDER_NUMBER = 0
+           CALL SELECT_FOLDER(.FALSE.,IER)
+           WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &              FOLDER(:TRIM(FOLDER))
+	   CALL UPDATE_USERINFO
+	   CALL OPEN_USERINFO
+	   INCMD = 'SHOW'
+	   CALL UPDATE_READ(0)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SHOW_LIBRARY
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	IF (CLI$PRESENT('ALL')) THEN 
+	   IER = 1
+	   N = 1
+	   DO WHILE (IER)
+	      IER = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',BULL_PARAMETER)
+	      IF (IER) THEN
+	         IF (N.EQ.1) THEN
+	            WRITE (6,'('' The following are valid libraries:'')')
+	   	    N = 0
+	         END IF
+	         WRITE (6,'(1X,A)') BULL_PARAMETER
+	      END IF
+	   END DO
+	   IF (N.EQ.1) WRITE (6,'('' No libraries are present.'')')
+	ELSE
+	   WRITE (6,'('' Present library is: '',A)')
+     &		FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_BULLNEWSDIR_FILE(FN)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+  
+        COMMON /NEWSDIR_FILE/ BULLNEWSDIR_FILE
+        CHARACTER*80 BULLNEWSDIR_FILE
+
+	BULLNEWSDIR_FILE = ' '
+  
+	ENCODE(6,'(I6)',BULLNEWSDIR_FILE) FN
+	BULLNEWSDIR_FILE = BULLNEWSDIR_FILE(FIRST_ALPHA(BULLNEWSDIR_FILE):)
+	L = TRIM(BULLNEWSDIR_FILE)
+
+	BULLNEWSDIR_FILE = FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWSDIR.'//
+     &		BULLNEWSDIR_FILE(:L-3)//']'//
+     &		BULLNEWSDIR_FILE(L-2:TRIM(BULLNEWSDIR_FILE))//'.'
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin7.for b/decus/vmslt98a/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..d8769ce19cb6c1b2cab9056bafc43a815b1d77e2
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin7.for
@@ -0,0 +1,2352 @@
+C
+C  BULLETIN7.FOR, Version 8/14/97
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE UPDATE_LOGIN(ADD_BULL)
+C
+C  SUBROUTINE UPDATE_LOGIN
+C
+C  FUNCTION:  Updates the login file when a bulletin has been deleted
+C	or added.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($SSDEF)'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	DIMENSION READ_BTIM_SAVE(2),TEMP_BTIM(2)
+
+	IF (FOLDER_NUMBER.GE.1000) GO TO 1000
+
+C
+C  We want to keep the last read date for comparison when selecting new
+C  folders, so save it for later restoring.
+C
+
+	READ_BTIM_SAVE(1) = READ_BTIM(1)
+	READ_BTIM_SAVE(2) = READ_BTIM(2)
+
+	CALL OPEN_BULLUSER_SHARED
+
+C
+C  Newest date/time in user file only applies to general bulletins.
+C  This was present before adding folder capability.
+C  We set flags in user entry to show new folder added for folder bulletins.
+C  However, the newest bulletin for each folder is not continually updated,
+C  As it is only used when comparing to the last bulletin read time, and to
+C  store this for each folder would be too expensive.
+C
+
+	TEMP_BTIM(1) = NEWEST_BTIM(1)
+	TEMP_BTIM(2) = NEWEST_BTIM(2)
+	CALL READ_USER_FILE_HEADER(IER)
+	NEWEST_BTIM(1) = TEMP_BTIM(1)
+	NEWEST_BTIM(2) = TEMP_BTIM(2)
+
+	IF (IER.NE.0) THEN
+	   CALL CLOSE_BULLUSER
+	   RETURN
+	ELSE IF (FOLDER_NUMBER.EQ.0) THEN
+	   CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,NEWEST_BTIM)
+	   REWRITE (4,IOSTAT=IER) USER_HEADER
+	END IF
+
+1000	BROAD_MSG = .FALSE.
+	IF (ADD_BULL.AND.FOLDER_NUMBER.GE.0) THEN	! Message added?
+	   IF (INCMD(:3).NE.'ADD') THEN
+	      BROAD_MSG = .TRUE.
+	   ELSE IF (.NOT.CLI$PRESENT('BROADCAST')) THEN
+	      BROAD_MSG = .TRUE.
+	   END IF
+	END IF
+
+	IF (BROAD_MSG) THEN
+	   IF (BTEST(FOLDER_FLAG,0)) THEN		! Folder protected?
+	      CALL CHKACL
+     &		(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',IER)
+	      IF (IER.EQ.(SS$_ACLEMPTY.OR.SS$_NORMAL)) THEN
+	         CHECK_ACL = 0
+	      ELSE
+	         CHECK_ACL = 1
+	      END IF
+	   ELSE
+	       CHECK_ACL = 0
+	   END IF
+
+ 	   CALL NOTIFY_USERS(CHECK_ACL)
+	END IF
+
+	IF (FOLDER_NUMBER.GE.1000) RETURN
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)
+		! Reobtain present values as calling programs still uses them
+
+	READ_BTIM(1) = READ_BTIM_SAVE(1)
+	READ_BTIM(2) = READ_BTIM_SAVE(2)
+
+	CALL CLOSE_BULLUSER
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE NOTIFY_USERS(CHECK_ACL)
+C
+C  SUBROUTINE NOTIFY_USERS
+C
+C  FUNCTION: Notify users with SET NOTIFY set of new message.
+C
+	IMPLICIT INTEGER (A - Z)
+	
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE '($BRKDEF)'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER OUTPUT*160,TERMINAL*8,FLAGS*4
+	CHARACTER*12 SENT_TEMP_USER,TEMP_USERNAME
+	CHARACTER NEWS_ACCESS*132
+	CHARACTER FOLDER_NAME_SAVE*80
+
+	INTEGER SAVE_LAST_NEWS_READ(2,FOLDER_MAX)
+
+	PARAMETER CR=CHAR(13),LF=CHAR(10),BELL=CHAR(7)
+
+	DATA FIRST/.TRUE./, BROAD1_USER_QUEUE/0/, TEMP_USER_QUEUE/0/
+
+	OUTPUT = BELL//CR//LF//LF//
+     &		'New bulletin added to folder '//FOLDER_NAME(:
+     &		TRIM(FOLDER_NAME))
+     &		//'. From: '//FROM(:TRIM(FROM))//CR//LF//
+     &		'Description: '//DESCRIP(:TRIM(DESCRIP))
+
+	IF (FIRST) THEN
+	   IER = SYS_TRNLNM('BULL_SYSTEM_FLAGS',FLAGS)
+	   IF (.NOT.IER) THEN
+	      IER = SYS_TRNLNM('MAIL$SYSTEM_FLAGS',FLAGS)
+	   END IF
+
+	   BFLAG = 0
+	   READ (FLAGS(:1),'(I1)',IOSTAT=IER) FLAG
+	   IF (BTEST(FLAG,1).AND.IER.EQ.0) BFLAG = BRK$M_CLUSTER
+	   FIRST = .FALSE.
+	   FOLDER1_NAME = ' '
+	END IF
+
+	CALL SYS$SETRWM(%VAL(1))		! Don't wait if can't broadcast
+
+	CALL INIT_QUEUE(BROAD1_USER_QUEUE,TEMP_USERNAME)
+	BROAD_USER_QUEUE = BROAD1_USER_QUEUE
+	IF (FOLDER_NAME_SAVE.EQ.FOLDER_NAME) THEN 
+           TEMP_USERNAME = ' '
+	   DO WHILE (TEMP_USERNAME.NE.'*')
+	      CALL READ_QUEUE(%VAL(BROAD_USER_QUEUE),BROAD_USER_QUEUE,
+     &				   TEMP_USERNAME)
+	      IF (TEMP_USERNAME.NE.'*') THEN
+	         CALL SYS$BRKTHRU(,OUTPUT(:TRIM(OUTPUT))//CR,
+     &			TEMP_USERNAME(:TRIM(TEMP_USERNAME)),
+     &			%VAL(BRK$C_USERNAME),,,%VAL(BFLAG),,%VAL(5),,)
+	      END IF
+	   END DO
+           CALL SYS$SETRWM(%VAL(0))
+	   RETURN
+	END IF
+
+	FOLDER_NAME_SAVE = FOLDER_NAME
+
+	IF (REMOTE_SET.EQ.4) THEN
+	   CALL OPEN_BULLINF_SHARED
+           CALL LIB$MOVC3(4*2*FOLDER_MAX,LAST_NEWS_READ,
+     &				SAVE_LAST_NEWS_READ)
+	END IF
+
+	CALL INIT_QUEUE(TEMP_USER_QUEUE,TEMP_USERNAME)
+	CALL INIT_QUEUE(BROAD1_USER_QUEUE,TEMP_USERNAME)
+	WRITE_TEMP_QUEUE = TEMP_USER_QUEUE
+	BROAD_USER_QUEUE = BROAD1_USER_QUEUE
+
+	DO WHILE (GETUSERS(TEMP_USERNAME,TERMINAL))
+	   READ_TEMP_QUEUE = TEMP_USER_QUEUE
+	   SENT_TEMP_USER = ' '
+	   DO WHILE (TEMP_USERNAME.NE.SENT_TEMP_USER.AND.
+     &				READ_TEMP_QUEUE.NE.WRITE_TEMP_QUEUE)
+		 CALL READ_QUEUE(%VAL(READ_TEMP_QUEUE),READ_TEMP_QUEUE,
+     &				SENT_TEMP_USER)
+	   END DO
+	   IF (TEMP_USERNAME.NE.SENT_TEMP_USER) THEN
+              IF (REMOTE_SET.EQ.4) THEN 
+	         CALL READ_NEWS_USERINFO(TEMP_USERNAME,IER)
+	      ELSE
+	         CALL READ_USER_FILE_KEYNAME(TEMP_USERNAME,IER)
+	      END IF
+              CALL WRITE_QUEUE(%VAL(WRITE_TEMP_QUEUE),WRITE_TEMP_QUEUE,
+     &				TEMP_USERNAME)
+	   ELSE
+	      IER = 2
+	   END IF
+	   IF (IER.EQ.0.AND.TEMP_USERNAME.NE.FROM.AND.
+     &	       TEST_NOTIFY_FLAG(FOLDER_NUMBER)) THEN
+	      IF (CHECK_ACL) THEN
+	         IF (REMOTE_SET.EQ.4) THEN
+	            CALL CHECK_ACCESS
+     &		     (NEWS_ACCESS(FOLDER_DESCRIP),
+     &		     TEMP_USERNAME,IER,WRITE_ACCESS)
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',
+     &		     TEMP_USERNAME,IER,WRITE_ACCESS)
+	         END IF
+	      ELSE
+		 IER = 1
+	      END IF
+	      IF (IER) THEN
+		 CALL SYS$BRKTHRU(,OUTPUT(:TRIM(OUTPUT))//CR,
+     &			TEMP_USERNAME(:TRIM(TEMP_USERNAME)),
+     &			%VAL(BRK$C_USERNAME),,,%VAL(BFLAG),,%VAL(5),,)
+                 CALL WRITE_QUEUE(%VAL(BROAD_USER_QUEUE),
+     &					BROAD_USER_QUEUE,TEMP_USERNAME)
+	      ELSE IF (REMOTE_SET.LT.3) THEN 
+		 CALL CLR2(NOTIFY_FLAG,FOLDER_NUMBER)
+	         REWRITE (4,IOSTAT=IER) TEMP_USERNAME//USER_ENTRY(13:)
+	      END IF
+	   END IF
+	END DO
+	CALL SYS$SETRWM(%VAL(0))
+
+        IF (REMOTE_SET.EQ.4) THEN
+           CALL CLOSE_BULLINF
+           CALL LIB$MOVC3(4*2*FOLDER_MAX,SAVE_LAST_NEWS_READ,
+     &				LAST_NEWS_READ)
+        END IF
+
+	FOLDER1_NAME = FOLDER_NAME
+
+	TEMP_USERNAME = '*'
+        CALL WRITE_QUEUE(%VAL(BROAD_USER_QUEUE),BROAD_USER_QUEUE,
+     &				TEMP_USERNAME)
+
+	RETURN
+	END
+
+
+
+
+ 
+	SUBROUTINE ADD_ENTRY
+C
+C  SUBROUTINE ADD_ENTRY
+C
+C  FUNCTION: Enters a new directory entry in the directory file.
+C
+	IMPLICIT INTEGER (A - Z)
+	
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+	
+	CHARACTER TODAY_TIME*32
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+        COMMON /LOCALPOST/ LOCAL_POST
+
+	IF (REMOTE_SET) THEN
+	   LOCAL = .TRUE.
+	   IF (INCMD(:3).EQ.'ADD') LOCAL = CLI$PRESENT('LOCAL')
+	   IF (LOCAL) THEN
+	      WRITE (REMOTE_UNIT,'(9A)',IOSTAT=IER)
+     &			3,DESCRIP,EXDATE,EXTIME,SYSTEM,0,0,0,0
+	   ELSE
+	      WRITE (REMOTE_UNIT,'(9A)',IOSTAT=IER)
+     &		3,DESCRIP,EXDATE,EXTIME,SYSTEM,CLI$PRESENT('BROADCAST'),
+     &		CLI$PRESENT('BELL'),CLI$PRESENT('ALL'),
+     &		CLI$PRESENT('CLUSTER')
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      READ(REMOTE_UNIT,'(Q,A)',IOSTAT=IER) I,FOLDER1_COM
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      IF (I.EQ.LEN(FOLDER1_COM)) THEN
+	         IER = SYS$ASCTIM(,TODAY_TIME,F1_NEWEST_BTIM,)
+	         NEWEST_DATE = TODAY_TIME(:11)
+	         NEWEST_TIME = TODAY_TIME(13:23)
+	         NBULL = F1_NBULL
+		 CALL UPDATE_FOLDER
+	      ELSE
+		 WRITE (6,'(1X,A)') FOLDER1_COM(:I)
+	      END IF
+	   ELSE
+	      CALL DISCONNECT_REMOTE
+	      IF (INCMD(:4).EQ.'MOVE') CALL EXIT
+	   END IF
+	   CALL UPDATE_LOGIN(.TRUE.)
+	   RETURN
+	END IF
+
+	CALL READDIR(0,IER)
+
+	IF (IER.NE.1) THEN
+	   NEWEST_EXDATE = '5-NOV-2056'
+	   NEWEST_EXTIME = '00:00:00.00'
+	   NEWEST_DATE = '5-NOV-1956'
+	   NEWEST_TIME = '00:00:00.00'
+	   NBULL = 0
+	   IF (REMOTE_SET.NE.4) NBLOCK = 0
+	   SHUTDOWN = 0
+	   NEMPTY = 0
+	END IF
+
+	CALL SYS$ASCTIM(,TODAY_TIME,,)
+       	NEWEST_DATE = TODAY_TIME(:11)  
+	NEWEST_TIME = TODAY_TIME(13:23)
+	IF (.NOT.LOCAL_POST) THEN
+	   DATE = NEWEST_DATE
+	   TIME = NEWEST_TIME
+	END IF
+	 
+	IF (.NOT.BTEST(FOLDER_FLAG,13)) THEN
+	   DIFF = COMPARE_DATE(NEWEST_EXDATE,EXDATE)
+	   IF (DIFF.GT.0) THEN
+	      NEWEST_EXDATE = EXDATE
+	      NEWEST_EXTIME = EXTIME
+	   ELSE IF (DIFF.EQ.0) THEN
+	      DIFF = COMPARE_TIME(NEWEST_EXTIME,EXTIME)
+	      IF (DIFF.GT.0) NEWEST_EXTIME = EXTIME
+	   END IF
+	END IF
+
+	IF ((SYSTEM.AND.4).EQ.4) THEN
+	   SHUTDOWN = SHUTDOWN + 1
+	   SHUTDOWN_DATE = DATE
+	   SHUTDOWN_TIME = TIME
+	END IF
+
+	IF (REMOTE_SET.EQ.4) THEN
+	   BLOCK = NBLOCK - LENGTH
+	   CALL WRITEDIR(NEWS_F_END+1,IER)
+	ELSE
+	   BLOCK = NBLOCK + 1
+	   CALL WRITEDIR(NBULL+1,IER)
+	END IF
+
+	IF (IER.NE.0) RETURN
+
+	IF (REMOTE_SET.EQ.4) THEN
+	   NEWS_F_END = NEWS_F_END + 1
+           NBULL = NEWS_F_END
+	   F_NBULL = NEWS_F_END
+	ELSE
+	   NBULL = NBULL + 1
+ 	   NBLOCK = NBLOCK + LENGTH
+	END IF
+
+	CALL WRITEDIR(0,IER)
+
+	IF (BTEST(FOLDER_FLAG,13)) THEN
+    	   CALL READ_FIRST_EXPIRED(NDEL)
+	   DO WHILE (NDEL.GT.0.AND.NDEL.LE.NEWS_F_END.AND.
+     &		COMPARE_BTIM(EX_BTIM,NEWEST_EXBTIM).LT.0)
+	      IF (LENGTH.GT.0) CALL DUMP_MESSAGE()
+	      DELETE (UNIT=2)
+    	      CALL READ_FIRST_EXPIRED(NDEL)
+	   END DO
+	   CALL OPEN_BULLNEWS_SHARED
+	   CALL READ_FOLDER_FILE_KEYNAME(NEWS_FOLDER,IER)
+	   FOLDER_FLAG = IBCLR(FOLDER_FLAG,13)
+	   CALL REWRITE_FOLDER_FILE(IER)
+	   CALL CLOSE_BULLNEWS
+	END IF
+
+	INQUIRE (UNIT=2,OPENED=IER)
+	IF (IER) CALL CLOSE_BULLDIR
+	CALL UPDATE_LOGIN(.TRUE.)
+	IF (IER) CALL OPEN_BULLDIR
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION COMPARE_BTIM(BTIM1,BTIM2)
+C
+C  FUNCTION COMPARE_BTIM
+C
+C  FUCTION: Compares times in binary format to see which is farther in future.
+C
+C  INPUTS:
+C	BTIM1  -  First time in binary format
+C	BTIM2  -  Second time in binary format
+C  OUTPUT:
+C	Returns +1 if first time is farther in future
+C	Returns -1 if second time is farther in future
+C	Returns 0 if equal time
+C
+	IMPLICIT INTEGER (A - Z)
+
+	DIMENSION BTIM1(2),BTIM2(2),DIFF(2)
+
+	CALL LIB$SUBX(BTIM1,BTIM2,DIFF)
+
+	IF (DIFF(2).LT.0) THEN
+	   COMPARE_BTIM = -1
+	ELSE IF (DIFF(2).GE.0) THEN
+	   COMPARE_BTIM = +1
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	INTEGER FUNCTION MINUTE_DIFF(DATE2,DATE1)
+C
+C  FUNCTION MINUTE_DIFF
+C
+C  FUNCTION: Finds difference in minutes between 2 binary times.
+C
+C
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION DATE1(2),DATE2(2)
+
+	CALL LIB$DAY(DAYS1,DATE1,MSECS1)
+	CALL LIB$DAY(DAYS2,DATE2,MSECS2)
+
+	MINUTE_DIFF = (DAYS2-DAYS1)*24*60 + (MSECS2-MSECS1)/6000
+
+	RETURN
+	END
+
+
+
+
+
+ 
+	INTEGER FUNCTION COMPARE_DATE(DATE1,DATE2)
+C
+C  FUNCTION COMPARE_DATE
+C
+C  FUCTION: Compares dates to see which is farther in future.
+C
+C  INPUTS:
+C	DATE1  -  First date  (dd-mm-yy)
+C	DATE2  -  Second date (If is equal to ' ', then use present date)
+C  OUTPUT:
+C	Returns the difference in days between the two dates.
+C	If the DATE1 is farther in the future, the output is positive,
+C	else it is negative.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	CHARACTER*(*) DATE1,DATE2
+	INTEGER USER_TIME(2)
+
+	CALL SYS_BINTIM(DATE1,USER_TIME)
+
+	CALL VERIFY_DATE(USER_TIME)
+C
+C  LIB$DAY crashes if date invalid, which happened once due to an unknown
+C  hardware or software error which created a date very far in the future.
+C
+	CALL LIB$DAY(DAY1,USER_TIME)
+
+	IF (DATE2.NE.' ') THEN
+	   CALL SYS_BINTIM(DATE2,USER_TIME)
+	   CALL VERIFY_DATE(USER_TIME)
+	ELSE
+	   CALL SYS$GETTIM(USER_TIME)
+	END IF
+
+	CALL LIB$DAY(DAY2,USER_TIME)
+
+	COMPARE_DATE = DAY1 - DAY2
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE VERIFY_DATE(BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION BTIM(2),TEMP(2)
+
+	CALL SYS_BINTIM(' 5-NOV-2011 00:00:00.00',TEMP)
+
+	IER = COMPARE_BTIM(BTIM,TEMP)
+
+	IF (IER.GT.0) THEN		! Date invalid
+	   BTIM(1) = TEMP(1)
+	   BTIM(2) = TEMP(2)
+	END IF
+
+	CALL SYS_BINTIM(' 5-NOV-1955 00:00:00.00',TEMP)
+
+	IER = COMPARE_BTIM(BTIM,TEMP)
+
+	IF (IER.LT.0) THEN		! Date invalid
+	   BTIM(1) = TEMP(1)
+	   BTIM(2) = TEMP(2)
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION COMPARE_TIME(TIME1,TIME2)
+C
+C  FUNCTION COMPARE_TIME
+C
+C  FUCTION: Compares times to see which is farther in future.
+C
+C  INPUTS:
+C	TIME1  -  First time	(hh:mm:ss.xx)
+C	TIME2  -  Second time
+C  OUTPUT:
+C	Outputs (TIME1-TIME2) in seconds.  Thus, if TIME1 is further
+C	in the future, outputs positive number, else negative.
+C
+
+	IMPLICIT INTEGER (A-Z)
+	CHARACTER*(*) TIME1,TIME2
+	CHARACTER*24 TODAY_TIME
+	CHARACTER*12 TEMP2
+
+	IF (TIME2.EQ.' ') THEN
+	   CALL SYS$ASCTIM(,TODAY_TIME,,)
+	   TEMP2 = TODAY_TIME(13:23)
+	ELSE
+	   TEMP2 = TIME2
+	END IF
+
+	COMPARE_TIME = 3600*10*(ICHAR(TIME1(:1))-ICHAR(TEMP2(:1)))
+     &		         +3600*(ICHAR(TIME1(2:2))-ICHAR(TEMP2(2:2)))
+     &		        +60*10*(ICHAR(TIME1(4:4))-ICHAR(TEMP2(4:4)))
+     &		           +60*(ICHAR(TIME1(5:5))-ICHAR(TEMP2(5:5)))
+     &		           +10*(ICHAR(TIME1(7:7))-ICHAR(TEMP2(7:7)))
+     &		              +(ICHAR(TIME1(8:8))-ICHAR(TEMP2(8:8)))
+
+	IF (COMPARE_TIME.EQ.0) THEN
+	   COMPARE_TIME = 10*(ICHAR(TIME1(10:10))-ICHAR(TEMP2(10:10)))
+     &		            +(ICHAR(TIME1(11:11))-ICHAR(TEMP2(11:11)))
+	   IF (COMPARE_TIME.GT.0) THEN
+	      COMPARE_TIME = 1
+	   ELSE IF (COMPARE_TIME.LT.0) THEN
+	      COMPARE_TIME = -1
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+C-------------------------------------------------------------------------
+C
+C  The following are subroutines to create a linked-list queue for 
+C  temporary buffer storage of data that is read from files to be
+C  outputted to the terminal.  This is done so as to be able to close
+C  the file as soon as possible.
+C
+C  Each record in the queue has the following format.  The first two
+C  words are used for creating a character variable.  The first word
+C  contains the length of the character variable, the second contains
+C  the address.  The address is simply the address of the 3rd word of
+C  the record.  The last word in the record contains the address of the
+C  next record.  Every time a record is written, if that record has a
+C  zero link, it adds a new record for the next write operation. 
+C  Therefore, there will always be an extra record in the queue.  To
+C  check for the end of the queue, the last word (link to next record)
+C  is checked to see if it is zero. 
+C
+C-------------------------------------------------------------------------
+	SUBROUTINE INIT_QUEUE(HEADER,DATA)
+	CHARACTER*(*) DATA
+	INTEGER HEADER
+	IF (HEADER.NE.0) RETURN		! Queue already initialized
+	LENGTH = LEN(DATA)
+	IF (MOD(LENGTH,4).NE.0) LENGTH = LENGTH + 4 - MOD(LENGTH,4)
+	CALL LIB$GET_VM(LENGTH+12,HEADER)
+	CALL MAKE_CHAR(%VAL(HEADER),LEN(DATA),LENGTH)
+	RETURN
+	END
+
+
+	SUBROUTINE WRITE_QUEUE(RECORD,NEXT,DATA)
+	INTEGER RECORD(1)
+	CHARACTER*(*) DATA
+	LENGTH = RECORD(1)
+	CALL COPY_CHAR(LENGTH,DATA,%VAL(%LOC(RECORD)))
+	IF (MOD(LENGTH,4).NE.0) LENGTH = LENGTH + 4 - MOD(LENGTH,4)
+	NEXT = RECORD((LENGTH+12)/4)
+	IF (NEXT.NE.0) RETURN
+	CALL LIB$GET_VM(LENGTH+12,NEXT)
+	CALL MAKE_CHAR(%VAL(NEXT),RECORD(1),LENGTH)
+	RECORD((LENGTH+12)/4) = NEXT
+	RETURN
+	END
+
+	SUBROUTINE READ_QUEUE(RECORD,NEXT,DATA)
+	CHARACTER*(*) DATA
+	INTEGER RECORD(1)
+	LENGTH = RECORD(1)
+	CALL COPY_CHAR(LENGTH,%VAL(%LOC(RECORD)),DATA)
+	IF (MOD(LENGTH,4).NE.0) LENGTH = LENGTH + 4 - MOD(LENGTH,4)
+	NEXT = RECORD((LENGTH+12)/4)
+	RETURN
+	END
+
+	SUBROUTINE COPY_CHAR(LENGTH,INCHAR,OUTCHAR)
+	CHARACTER*(*) INCHAR,OUTCHAR
+	OUTCHAR = INCHAR(:LENGTH)
+	RETURN
+	END
+
+	SUBROUTINE MAKE_CHAR(IARRAY,CHAR_LEN,REAL_LEN)
+	IMPLICIT INTEGER (A-Z)
+	DIMENSION IARRAY(1)
+	IARRAY(1) = CHAR_LEN
+	IARRAY(2) = %LOC(IARRAY(3))
+	IARRAY(REAL_LEN/4+3) = 0
+	RETURN
+	END
+
+
+
+	SUBROUTINE DISABLE_PRIVS
+C
+C  SUBROUTINE DISABLE_PRIVS
+C
+C  FUNCTION: Disable image high privileges.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($PRVDEF)'
+
+	COMMON /PRIVS/ SETPRV,PRV_DEPTH
+	DIMENSION SETPRV(2)
+
+	DATA PRV_DEPTH /0/
+
+	COMMON /REALPROC/ REALPROCPRIV(2)
+
+	PRV_DEPTH = PRV_DEPTH + 1
+
+	IF (PRV_DEPTH.GT.1) RETURN
+
+	CALL SYS$SETPRV(%VAL(0),,,SETPRV)	! Get privileges
+
+	SETPRV(1) = SETPRV(1).AND..NOT.REALPROCPRIV(1)
+
+	CALL SYS$SETPRV(%VAL(0),SETPRV,,)	! Disable installed privs
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ENABLE_PRIVS
+C
+C  SUBROUTINE ENABLE_PRIVS
+C
+C  FUNCTION: Enable image high privileges.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVS/ SETPRV,PRV_DEPTH
+	DIMENSION SETPRV(2)
+
+	PRV_DEPTH = PRV_DEPTH - 1
+
+	IF (PRV_DEPTH.GT.1) RETURN
+
+	CALL SYS$SETPRV(%VAL(1),SETPRV,,)	! Enable image privs
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CHECK_PRIV_IO(ERROR)
+C
+C  SUBROUTINE CHECK_PRIV_IO
+C
+C  FUNCTION: Checks SYS$OUTPUT and SYS$ERROR to see if they need
+C	privileges to output to.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /OUTPUT/ REASSIGNED
+	LOGICAL REASSIGNED
+	DATA REASSIGNED /.FALSE./
+
+	CALL DISABLE_PRIVS			! Disable SYSPRV 
+
+	IF (.NOT.REASSIGNED) THEN
+	   OPEN (UNIT=6,FILE='SYS$OUTPUT',IOSTAT=IER,STATUS='NEW')
+	   CLOSE (UNIT=6,STATUS='DELETE')
+	END IF
+
+	OPEN (UNIT=4,FILE='SYS$ERROR',IOSTAT=IER1,STATUS='NEW')
+	IF (IER.NE.0.OR.IER1.NE.0) THEN
+	   IF (IER1.EQ.0) WRITE (4,100)
+	   IF (IER.EQ.0) WRITE (6,200)
+	   ERROR = 1
+	ELSE
+	   CLOSE (UNIT=4,STATUS='DELETE')
+	   ERROR = 0
+	END IF
+
+	CALL ENABLE_PRIVS			! Enable SYSPRV 
+
+100	FORMAT(1X,'ERROR: SYS$OUTPUT cannot be opened.')
+200	FORMAT(1X,'ERROR: SYS$ERROR cannot be opened.')
+
+	RETURN
+	END
+
+
+	SUBROUTINE CHANGE_FLAG(CMD,FLAG)
+C
+C  SUBROUTINE CHANGE_FLAG
+C
+C  FUNCTION: Sets flags for specified folder.
+C
+C  INPUTS:
+C	CMD    -   LOGICAL*4 value. If TRUE, set flag. 
+C		   If FALSE, clear flag.
+C	FLAG	-  If 1, modify NEW_FLAG, if 2, modify SET_FLAG
+C		   If 3, modify BRIEF_FLAG, 4, modify NOTIFY_FLAG
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /BULL_NOTIFY/ NOTIFY_REMOTE(FLONG)
+
+	DIMENSION FLAGS(FLONG,4)
+	EQUIVALENCE (NEW_FLAG(1),FLAGS(1,1))
+
+	LOGICAL CMD
+
+	DIMENSION READ_BTIM_SAVE(2)
+
+	DATA CHANGE_FOLDER /.FALSE./
+
+	IF (CLI$PRESENT('FOLDER')) THEN
+	   IER = CLI$GET_VALUE('FOLDER',FOLDER1)
+	   IF (IER) THEN
+	      FOLDER_NUMBER_SAVE = FOLDER_NUMBER
+	      CALL OPEN_BULLFOLDER_SHARED
+	      CALL READ_FOLDER_FILE_KEYNAME_TEMP(FOLDER1,IER)
+	      CALL CLOSE_BULLFOLDER
+	      IF (IER.NE.0) THEN
+	         WRITE (6,'('' ERROR: No such folder found.'')')
+	         RETURN
+	      ELSE IF (INDEX(FOLDER1,'.').GT.0.OR.
+     &		 (FOLDER1(:1).GE.'a'.AND.FOLDER1(:1).LE.'z')) THEN
+	         WRITE (6,'('' ERROR: Command not valid for folder.'')')
+	         RETURN
+	      END IF
+	   END IF
+	   FOLDER_NUMBER = FOLDER1_NUMBER
+	   CHANGE_FOLDER = .TRUE.
+	END IF
+
+C
+C  Find user entry in BULLUSER.DAT to update information.
+C
+
+	ENTRY CHANGE_FLAG_NOCMD(CMD,FLAG)
+
+	CALL OPEN_BULLUSER_SHARED		! Open user file
+
+	READ_BTIM_SAVE(1) = READ_BTIM(1)
+	READ_BTIM_SAVE(2) = READ_BTIM(2)
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)	! Read old entry
+
+	IF (IER.GT.0) THEN 		! No entry (how did this happen??)
+	   CALL SYS_BINTIM('-',LOGIN_BTIM)	! Get today's today
+	   CALL SYS_BINTIM('5-NOV-1956 11:05:56',READ_BTIM)	! Fake new entry
+	   CALL READ_USER_FILE_HEADER(IER)
+	   IF (CMD) THEN
+	      CALL SET2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   ELSE
+	      CALL CLR2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   END IF
+	   NEW_FLAG(1) = 143
+	   NEW_FLAG(2) = 0
+	   CALL WRITE_USER_FILE_NEW(IER)
+	ELSE
+	   IF (CMD) THEN
+	      CALL SET2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   ELSE
+	      CALL CLR2(FLAGS(1,FLAG),FOLDER_NUMBER)
+	   END IF
+	   NEW_FLAG(1) = 143
+	   REWRITE (4,IOSTAT=IER) USER_ENTRY
+	   READ_BTIM(1) = READ_BTIM_SAVE(1)
+	   READ_BTIM(2) = READ_BTIM_SAVE(2)
+	END IF
+
+	IF (CMD.AND.FLAG.EQ.4.AND.FOLDER_BBOARD(:2).EQ.'::') THEN
+	   DO WHILE (REC_LOCK(IER))
+	      READ (4,KEY='*NOTIFY',IOSTAT=IER) TEMP_USER,NOTIFY_REMOTE
+	   END DO
+
+	   IF (IER.NE.0) THEN
+	      DO I=1,FLONG
+	         NOTIFY_REMOTE(I) = 0
+	      END DO
+	      CALL SET2(NOTIFY_REMOTE,FOLDER_NUMBER)
+	      WRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	   ELSE
+	      CALL SET2(NOTIFY_REMOTE,FOLDER_NUMBER)
+	      REWRITE (4,IOSTAT=IER) '*NOTIFY     ',NOTIFY_REMOTE
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLUSER
+
+	IF (CHANGE_FOLDER) THEN
+	   FOLDER_NUMBER = FOLDER_NUMBER_SAVE
+	   CHANGE_FOLDER = .FALSE.
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE SET_VERSION
+C
+C  SUBROUTINE SET_VERSION
+C
+C  FUNCTION: Sets version number.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	DIMENSION FLAGS(FLONG,4)
+	EQUIVALENCE (NEW_FLAG(1),FLAGS(1,1))
+
+	DIMENSION READ_BTIM_SAVE(2)
+
+C
+C  Find user entry in BULLUSER.DAT to update information.
+C
+
+	CALL OPEN_BULLUSER_SHARED		! Open user file
+
+	READ_BTIM_SAVE(1) = READ_BTIM(1)
+	READ_BTIM_SAVE(2) = READ_BTIM(2)
+
+	CALL READ_USER_FILE_KEYNAME(USERNAME,IER)	! Read old entry
+
+	IF (IER.EQ.0) THEN
+	   NEW_FLAG(1) = 143
+	   REWRITE (4,IOSTAT=IER) USER_ENTRY  ! Write modified entry
+	   READ_BTIM(1) = READ_BTIM_SAVE(1)
+	   READ_BTIM(2) = READ_BTIM_SAVE(2)
+	END IF
+
+	CALL CLOSE_FILE (4)
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE CHECK_NEWUSER(USERNAME,DISMAIL,PASSCHANGE)
+C
+C  SUBROUTINE CHECK_NEWUSER
+C
+C  FUNCTION: Checks flags for a new: Whether DISMAIL is set,
+C		and what the last password change was.
+C
+C  INPUTS:
+C	USERNAME  -  Username
+C  OUTPUTS:
+C  	DISMAIL     -  Returns 1 if account has DISMAIL.
+C		       returns 0 if account has no DISMAIL.
+C	PASSCHANGE  -  Date of last password change.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) USERNAME
+
+	INTEGER PASSCHANGE(2)
+
+	INCLUDE '($UAIDEF)'
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(4,UAI$_FLAGS,%LOC(FLAGS))
+	CALL ADD_2_ITMLST(8,UAI$_PWD_DATE,%LOC(PASSCHANGE))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	DISMAIL = 0					! Set return false
+	IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)	! Read Record
+	IF (IER) THEN					! If username found
+	   IF (BTEST(FLAGS,UAI$V_NOMAIL)) THEN		! DISMAIL SET?
+	      DISMAIL = 1				! Yep
+	   END IF
+	END IF
+
+	RETURN						! Return
+	END						! End
+
+
+
+	INTEGER FUNCTION SYS_TRNLNM(INPUT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+        PARAMETER LNM$_STRING = '2'X
+
+	IF (INDEX(INPUT,']').GT.0) THEN
+	   SYS_TRNLNM = .FALSE.
+	   RETURN
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+	IF (OUTPUT.NE.'DEFINED') CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT),%LOC(OLEN))
+	CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+
+	EINPUT = INDEX(INPUT,':') - 1
+	IF (EINPUT.LE.0) EINPUT = TRIM(INPUT)
+
+	SYS_TRNLNM = SYS$TRNLNM(,'LNM$FILE_DEV',INPUT(:EINPUT),,
+     &		%VAL(TRNLNM_ITMLST))
+
+	IF (SYS_TRNLNM.AND.OUTPUT.NE.'DEFINED') OUTPUT = OUTPUT(:OLEN)
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION SYS_TRNLNM_SYSTEM_INDEX(INPUT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+        PARAMETER LNM$_STRING = '2'X
+	PARAMETER LNM$_INDEX = '1'X
+	PARAMETER LNM$_MAX_INDEX = '7'X
+
+	DATA NINDEX /0/
+
+	IF (MAX_INDEX.LT.NINDEX) THEN
+	   NINDEX = 0
+	   SYS_TRNLNM_SYSTEM_INDEX = 0
+	   RETURN
+	END IF
+
+	EINPUT = INDEX(INPUT,':') - 1
+	IF (EINPUT.LE.0) EINPUT = TRIM(INPUT)
+
+	IF (NINDEX.EQ.0) THEN 
+	   CALL INIT_ITMLST	! Initialize item list
+	   CALL ADD_2_ITMLST(4,LNM$_MAX_INDEX,%LOC(MAX_INDEX))
+	   CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+ 	   SYS_TRNLNM_SYSTEM_INDEX = SYS$TRNLNM(,'LNM$SYSTEM',
+     &		INPUT(:EINPUT),,%VAL(TRNLNM_ITMLST))
+	   IF (.NOT.SYS_TRNLNM_SYSTEM_INDEX) RETURN
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,LNM$_INDEX,%LOC(NINDEX))
+	CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT),%LOC(OLEN))
+	CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+
+	SYS_TRNLNM_SYSTEM_INDEX = SYS$TRNLNM(,'LNM$SYSTEM',
+     &		INPUT(:EINPUT),,%VAL(TRNLNM_ITMLST))
+
+	IF (SYS_TRNLNM_SYSTEM_INDEX) OUTPUT = OUTPUT(:OLEN)
+	NINDEX = NINDEX  + 1
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION SYS_TRNLNM_SYSTEM(INPUT,OUTPUT)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INPUT,OUTPUT
+
+        PARAMETER LNM$_STRING = '2'X
+
+	CALL INIT_ITMLST	! Initialize item list
+	IF (OUTPUT.NE.'DEFINED') CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT),%LOC(OLEN))
+	CALL END_ITMLST(TRNLNM_ITMLST)	! Get address of itemlist
+
+	EINPUT = INDEX(INPUT,':') - 1
+	IF (EINPUT.LE.0) EINPUT = TRIM(INPUT)
+
+	SYS_TRNLNM_SYSTEM = SYS$TRNLNM(,'LNM$SYSTEM',
+     &		INPUT(:EINPUT),,%VAL(TRNLNM_ITMLST))
+
+	IF (SYS_TRNLNM_SYSTEM.AND.OUTPUT.NE.'DEFINED') THEN
+	   OUTPUT = OUTPUT(:OLEN)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION FILE_LOCK(IER,IER1)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($RMSDEF)'
+
+	DATA INIT /.TRUE./
+
+	IF (INIT) THEN
+	   FILE_LOCK = 1
+	   INIT = .FALSE.
+	   IER1 = 0
+	ELSE
+	   IF (IER.GT.0) THEN
+	      IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
+	      IF (IER1.EQ.RMS$_FLK) THEN
+	         FILE_LOCK = 1
+		 CALL WAIT_SEC('01')
+	      ELSE
+	         FILE_LOCK = 0
+	         INIT = .TRUE.
+	      END IF
+	   ELSE
+	      FILE_LOCK = 0
+	      IER1 = 0
+	      INIT = .TRUE.
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE ENABLE_CTRL
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /CTRL_LEVEL/ LEVEL
+
+	COMMON /DEF_PROT/ ORIGINAL_DEF_PROT
+
+        COMMON /KEYPAD/ KEYPAD_MODE
+
+	QUIT = 1
+
+	ENTRY ENABLE_CTRL_EXIT
+
+	QUIT = QUIT.AND.1		! If called via entry, QUIT = 0
+	IF (QUIT.EQ.1) LEVEL = LEVEL - 1
+
+	IF (LEVEL.LT.0.AND.QUIT.EQ.1) THEN
+	   WRITE (6,'('' ERROR: Error in CTRL.'')')
+	END IF
+
+	IF (LEVEL.EQ.0.OR.QUIT.EQ.0) THEN
+	   CALL LIB$ENABLE_CTRL(CTRLY,)	! Enable CTRL-Y & -C
+	END IF
+
+	IF (QUIT.EQ.0) THEN
+	   IF (KEYPAD_MODE.EQ.0) THEN
+	      IER = SMG$CREATE_VIRTUAL_KEYBOARD(KEYBOARD_ID,,,,)
+	      IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,1)
+	   END IF
+	   CALL CLOSE_TAG
+	   FOLDER_FLAG = 0
+	   CALL SET_FOLDER_FILE(0)
+	   CALL UPDATE_USERINFO
+	   CALL PRINT_NOW
+	   CALL SYS$SETDFPROT(ORIGINAL_DEF_PROT,)
+	   CALL EXIT
+	END IF
+	QUIT = 0			! Reinitialize
+
+	RETURN
+	END
+
+
+	SUBROUTINE DISABLE_CTRL
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /CTRLY/ CTRLY
+
+	COMMON /CTRL_LEVEL/ LEVEL
+	DATA LEVEL /0/
+
+	IF (LEVEL.EQ.0) CALL LIB$DISABLE_CTRL(CTRLY,)
+	LEVEL = LEVEL + 1
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CLEANUP_BULLFILE
+C
+C  SUBROUTINE CLEANUP_BULLFILE
+C
+C  FUNCTION:  Searches for empty space in bulletin file and deletes it.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	CHARACTER BUFFER*128
+
+	CALL OPEN_BULLDIR_SHARED
+
+C
+C  NOTE: Can't use READDIR for reading header since it'll spawn a 
+C  BULL/CLEANUP.  (Fooey).
+C
+
+	DO WHILE (REC_LOCK(IER))
+	   READ (2,KEYID=0,KEY=HEADER_KEY,IOSTAT=IER) BULLDIR_HEADER
+	END DO
+
+	IF (NEMPTY.EQ.0) THEN		! No cleanup necessary
+	 CALL CLOSE_BULLDIR
+	 RETURN
+	ELSE IF (NEMPTY.GT.0) THEN
+
+	 CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
+		! Set protection to (SYSTEM:RWED,OWNER:RWED,,)
+
+	 OPEN (UNIT=11,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL',
+     1	      STATUS='UNKNOWN',IOSTAT=IER,DISPOSE='DELETE',
+     1	      RECORDTYPE='FIXED',RECORDSIZE=32,
+     1	      FORM='UNFORMATTED',INITIALSIZE=((NBLOCK-NEMPTY)*128)/512)
+				! Compressed version is number 1
+
+	 IF (IER.NE.0) THEN
+	    WRITE (6,'('' Cannot open temporary file for''
+     &		,'' compressing '',A)') FOLDER(:TRIM(FOLDER))
+	    CALL ERRSNS(IDUMMY,IER)
+	    IF (IER1.EQ.0) THEN
+	       WRITE (6,'('' IOSTAT error = '',I)') IER
+	    ELSE
+	       CALL SYS_GETMSG(IER1)
+	    END IF
+	    CALL CLOSE_BULLDIR
+	    CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+	    RETURN
+	 END IF
+
+	 CALL COPY_ACL(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFIL',
+     &		       FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL')
+
+	 CALL OPEN_BULLFIL_SHARED		! Open bulletin file
+
+	 NBLOCK = 0
+
+	 DO I=1,NBULL				! Copy bulletins to new file
+	   CALL READDIR(I,IER)
+	   ICOUNT = BLOCK
+	   DO J=1,LENGTH
+	      NBLOCK = NBLOCK + 1
+	      DO WHILE (REC_LOCK(IER1))
+	         READ(1'ICOUNT,IOSTAT=IER1) BUFFER
+	      END DO
+	      IF (IER1.NE.0) THEN		! This file is corrupt
+		 NBLOCK = NBLOCK - 1
+		 NBULL = I - 1
+	         GO TO 100
+	      END IF
+	      WRITE(11) BUFFER
+	      ICOUNT = ICOUNT + 1
+	   END DO
+	 END DO
+
+100	 CALL CLOSE_BULLFIL
+	ELSE IF (NEMPTY.EQ.-1) THEN
+	 CALL CLOSE_BULLDIR
+	 CALL OPEN_BULLDIR	! Open with no sharing
+	 IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL',
+     &				'*.BULLFIL')
+	 IER = 1
+	 DO WHILE (IER)
+	    IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLFIL;-1')
+	 END DO
+	 IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPDIR',
+     &				'*.BULLDIR')
+	 CALL CLOSE_BULLDIR_DELETE
+	 IER = 1
+	 DO WHILE (IER)
+	    IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLDIR;-1')
+	 END DO
+	 IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULL*',
+     &				'*.*;1')
+	 RETURN
+	END IF
+
+	OPEN (UNIT=12,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.TMPDIR',STATUS='UNKNOWN',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED',
+     &	      INITIALSIZE=(((NBULL+1)*DIR_RECORD_LENGTH)/512)+1 )
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=12,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &	      //'.TMPDIR',STATUS='UNKNOWN',FORM='UNFORMATTED',
+     &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	    IF (IER.NE.0) THEN
+	       WRITE (6,'('' Cannot open temporary file for''
+     &		,'' compressing '',A)') FOLDER(:TRIM(FOLDER))
+	       CALL ERRSNS(IDUMMY,IER)
+	       IF (IER1.EQ.0) THEN
+	          WRITE (6,'('' IOSTAT error = '',I)') IER
+	       ELSE
+	          CALL SYS_GETMSG(IER1)
+	       END IF
+	       CLOSE (UNIT=11)
+	       CALL CLOSE_BULLDIR
+	       CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+	       RETURN
+	    END IF
+	END IF
+
+	CALL COPY_ACL(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLDIR',
+     &		       FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPDIR')
+
+	NEMPTY = 0
+	WRITE (12,IOSTAT=IER) BULLDIR_HEADER	! Write directory header
+
+	NBLOCK = 0		! Update directory entry pointers
+	DO I=1,NBULL
+	   CALL READDIR(I,IER)
+	   BLOCK = NBLOCK + 1
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   WRITE (12,IOSTAT=IER) BULLDIR_ENTRY
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' Cannot write to temporary file for''
+     &		,'' compressing '',A)') FOLDER(:TRIM(FOLDER))
+	      CALL ERRSNS(IDUMMY,IER)
+	      IF (IER1.EQ.0) THEN
+	         WRITE (6,'('' IOSTAT error = '',I)') IER
+	      ELSE
+	         CALL SYS_GETMSG(IER1)
+	      END IF
+	      CLOSE (UNIT=12)
+	      CLOSE (UNIT=11)
+	      CALL CLOSE_BULLDIR
+	      CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+	      RETURN
+	   END IF
+	   NBLOCK = NBLOCK + MAX(LENGTH,0)
+	END DO
+
+	CLOSE (UNIT=12,STATUS='KEEP')
+	CLOSE (UNIT=11,STATUS='KEEP')
+
+	CALL CLOSE_BULLDIR
+	CALL OPEN_BULLDIR	! Open with no sharing
+
+	NEMPTY = -1		! Copying done, indicate that in case of crash
+	WRITE (2,IOSTAT=IER) BULLDIR_HEADER ! Write new directory header
+
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPFIL',
+     &				'*.BULLFIL')
+	IER = 1
+	DO WHILE (IER)
+	   IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLFIL;-1')
+	END DO
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.TMPDIR',
+     &				'*.BULLDIR')
+	CALL CLOSE_BULLDIR_DELETE
+	IER = 1
+	DO WHILE (IER)
+	   IER = LIB$DELETE_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &				'.BULLDIR;-1')
+	END DO
+	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULL*',
+     &				'*.*;1')
+
+	CALL SYS$SETDFPROT(CUR_DEF_PROT,)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CLEANUP_DIRFILE(DELETE_ENTRY)
+C
+C  SUBROUTINE CLEANUP_DIRFILE
+C
+C  FUNCTION:  Reorder directory file after deletions.
+C	      Is called either directly after a deletion, or is
+C	      called if it is detected that a deletion was not fully
+C	      completed due to the fact that the deleting process
+C	      was abnormally terminated.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(DIR_RECORD_LENGTH) BULLDIR_ENTRY_SAVE
+
+	CHARACTER*12 DATE_SAVE,EXDATE_SAVE
+	CHARACTER*12 TIME_SAVE,EXTIME_SAVE
+
+	BULLDIR_ENTRY_SAVE = BULLDIR_ENTRY
+	DATE_SAVE = DATE
+	TIME_SAVE = TIME
+	EXDATE_SAVE = EXDATE
+	EXTIME_SAVE = EXTIME
+
+	NBULL = -NBULL		! Negative # Bulls signals deletion in progress
+	MOVE_TO = 0		! Moving directory entries starting here
+	MOVE_FROM = 0		! Moving directory entries from here
+	I = DELETE_ENTRY	! Start search point for first deleted entries
+	DO WHILE (MOVE_TO.EQ.0.AND.I.LE.NBULL)
+	   CALL READDIR(I,IER)
+	   IF (IER.NE.I+1) THEN	! Have we found a deleted entry?
+	      MOVE_TO = I	! If so, start moving entries to here
+	      J=I+1		! Search for next entry in file
+	      DO WHILE (MOVE_FROM.EQ.0.AND.J.LE.NBULL)
+		 CALL READDIR(J,IER)
+		 IF (IER.EQ.J+1) MOVE_FROM = J
+		 J = J + 1
+	      END DO
+	      IF (MOVE_FROM.EQ.0) THEN	! There are no more entries
+		 NBULL = I - 1		! so just update number of bulletins
+		 CALL WRITEDIR(0,IER)
+		 RETURN
+	      END IF
+	      LENGTH = -LENGTH		! Indicate starting point by writing
+	      CALL WRITEDIR(I,IER)	! next entry into deleted entry
+	      FIRST_DELETE = I		! with negative length
+	      MOVE_FROM = MOVE_FROM + 1	! Set up pointers to move rest of
+	      MOVE_TO = MOVE_TO + 1	! the entries
+	   ELSE IF (LENGTH.LT.0) THEN	! If negative length found, deletion
+	      FIRST_DELETE = I		! was previously in progress
+	      J = I			! Try to find where entry came from
+	      CALL INIT_QUEUE(ENTRY_Q1,BULLDIR_ENTRY)
+	      ENTRY_Q = ENTRY_Q1
+	      DO K=J,NBULL
+		 CALL READDIR(K,IER)
+	         IF (IER.EQ.K+1) THEN
+		    CALL WRITE_QUEUE(%VAL(ENTRY_Q),ENTRY_Q,BULLDIR_ENTRY)
+		 END IF
+	      END DO
+	      ENTRY_QLAST = ENTRY_Q
+	      ENTRY_Q2 = ENTRY_Q1
+	      DO WHILE (MOVE_FROM.EQ.0.AND.ENTRY_Q2.NE.ENTRY_QLAST)
+		 CALL READ_QUEUE(%VAL(ENTRY_Q2),ENTRY_Q,BULLDIR_ENTRY)
+		 ENTRY_Q2 = ENTRY_Q
+		 BLOCK_SAVE = BLOCK
+		 MSG_NUM_SAVE = MSG_NUM
+		 DO WHILE (MOVE_FROM.EQ.0.AND.ENTRY_Q.NE.ENTRY_QLAST)
+						! Search for duplicate entries
+		    CALL READ_QUEUE(%VAL(ENTRY_Q),ENTRY_Q,BULLDIR_ENTRY)
+		    IF (BLOCK_SAVE.EQ.BLOCK) THEN
+		       MOVE_TO = MSG_NUM_SAVE + 1
+		       MOVE_FROM = MSG_NUM + 1
+		    END IF
+		 END DO
+		 			! If no duplicate entry found for this
+					! entry, see if one exists for any
+	      END DO			! of the other entries
+	   END IF
+	   I = I + 1
+	END DO
+
+	IF (I.LE.NBULL) THEN		! Move reset of entries if necessary
+	   IF (MOVE_FROM.GT.0) THEN
+	      DO J=MOVE_FROM,NBULL
+	         CALL READDIR(J,IER)
+		 IF (IER.EQ.J+1) THEN	! Skip any other deleted entries
+		    CALL WRITEDIR(MOVE_TO,IER)
+		    MOVE_TO = MOVE_TO + 1
+		 END IF
+	      END DO
+	   END IF
+	   DO J=MOVE_TO,NBULL		! Delete empty records at end of file
+	      CALL READDIR(J,IER)
+	      DELETE(UNIT=2,IOSTAT=IER)
+	   END DO
+	   NBULL = MOVE_TO - 1		! Update # bulletin count
+	END IF
+
+	IF (FIRST_DELETE.GT.0) THEN
+	   CALL READDIR(FIRST_DELETE,IER)
+	   IF (IER.EQ.FIRST_DELETE+1.AND.LENGTH.LT.0) THEN
+	      LENGTH = -LENGTH		! Fix entry which has negative length
+	      CALL WRITEDIR(FIRST_DELETE,IER)
+	   END IF
+	END IF
+
+	CALL WRITEDIR(0,IER)
+
+	BULLDIR_ENTRY = BULLDIR_ENTRY_SAVE
+	DATE = DATE_SAVE
+	TIME = TIME_SAVE
+	EXDATE = EXDATE_SAVE
+	EXTIME = EXTIME_SAVE
+
+	RETURN
+	END
+
+
+	SUBROUTINE SHOW_FLAGS
+C
+C  SUBROUTINE SHOW_FLAGS
+C
+C  FUNCTION: Show user flags.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (FOLDER_NUMBER.LT.0) THEN
+	   WRITE (6,'('' ERROR: Cannot show flags for remote folder.'')')
+	   RETURN
+	END IF
+
+C
+C  Find user entry in BULLUSER.DAT to obtain flags.
+C
+	IF (REMOTE_SET.LT.3) THEN
+	   CALL OPEN_BULLUSER_SHARED		! Open user file
+	   CALL READ_USER_FILE_KEYNAME(USERNAME,IER)	! Read old entry
+	ELSE IF (NEWS_FIND_SUBSCRIBE().GT.FOLDER_MAX-1) THEN
+	   WRITE (6,'('' ERROR: NEWS FOLDER is not subscribed.'')')
+           RETURN
+ 	END IF
+
+	WRITE (6,'('' For the selected folder '',A)')
+     &	   FOLDER_NAME(:TRIM(FOLDER_NAME))
+
+	IF (TEST_SET_FLAG(FOLDER_NUMBER).AND.
+     &	   (.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER))) THEN
+	   WRITE (6,'('' READNEW is set.'')')
+	ELSE IF (TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &	       TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' BRIEF is set.'')')
+	ELSE IF (TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &	       .NOT.TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' SHOWNEW is set.'')')
+	END IF
+
+	IF (REMOTE_SET.NE.3.AND.TEST_NOTIFY_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' NOTIFY is set.'')')
+	ELSE IF (.NOT.TEST_BRIEF_FLAG(FOLDER_NUMBER).AND.
+     &	       .NOT.TEST_SET_FLAG(FOLDER_NUMBER)) THEN
+	   WRITE (6,'('' No flags are set.'')')
+	END IF
+
+	IF (REMOTE_SET.LT.3) CALL CLOSE_BULLUSER
+
+	RETURN
+	END
+
+
+	SUBROUTINE SET2(FLAG,NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER FLAG(2)
+
+	F_POINT = NUMBER/32 + 1
+	FLAG(F_POINT) = IBSET(FLAG(F_POINT),NUMBER-32*(F_POINT-1))
+
+	RETURN
+	END
+
+
+	SUBROUTINE CLR2(FLAG,NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER FLAG(3)
+
+	F_POINT = NUMBER/32 + 1
+	FLAG(F_POINT) = IBCLR(FLAG(F_POINT),NUMBER-32*(F_POINT-1))
+
+	RETURN
+	END
+
+
+
+	LOGICAL FUNCTION TEST2(FLAG,NUMBER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER FLAG(3)
+
+	F_POINT = NUMBER/32 + 1
+	TEST2 = BTEST(FLAG(F_POINT),NUMBER-32*(F_POINT-1))
+
+	RETURN
+	END
+
+
+
+
+	INTEGER FUNCTION GETUSERS(USERNAME,TERMINAL)
+C
+C  FUNCTION GETUSERS
+C
+C  FUNCTION:
+C	To get names of all users that are logged in.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+!*** MODULE $PSCANDEF ***
+	PARAMETER PSCAN$_BEGIN = '00000000'X
+	PARAMETER PSCAN$_ACCOUNT = '00000001'X
+	PARAMETER PSCAN$_AUTHPRI = '00000002'X
+	PARAMETER PSCAN$_CURPRIV = '00000003'X
+	PARAMETER PSCAN$_GRP = '00000004'X
+	PARAMETER PSCAN$_HW_MODEL = '00000005'X
+	PARAMETER PSCAN$_HW_NAME = '00000006'X
+	PARAMETER PSCAN$_JOBPRCCNT = '00000007'X
+	PARAMETER PSCAN$_JOBTYPE = '00000008'X
+	PARAMETER PSCAN$_MASTER_PID = '00000009'X
+	PARAMETER PSCAN$_MEM = '0000000A'X
+	PARAMETER PSCAN$_MODE = '0000000B'X
+	PARAMETER PSCAN$_NODE_CSID = '0000000C'X
+	PARAMETER PSCAN$_NODENAME = '0000000D'X	
+	PARAMETER PSCAN$_OWNER = '0000000E'X
+	PARAMETER PSCAN$_PRCCNT = '0000000F'X
+	PARAMETER PSCAN$_PRCNAM = '00000010'X
+	PARAMETER PSCAN$_PRI = '00000011'X
+	PARAMETER PSCAN$_PRIB = '00000012'X
+	PARAMETER PSCAN$_STATE = '00000013'X
+	PARAMETER PSCAN$_STS = '00000014'X
+	PARAMETER PSCAN$_TERMINAL = '00000015'X
+	PARAMETER PSCAN$_UIC = '00000016'X
+	PARAMETER PSCAN$_USERNAME = '00000017'X
+	PARAMETER PSCAN$_GETJPI_BUFFER_SIZE = '00000018'X
+	PARAMETER PSCAN$_END = '00000019'X
+	PARAMETER PSCAN$k_type = '00000081'X
+	PARAMETER PSCAN$M_OR = '00000001'X
+	PARAMETER PSCAN$M_BIT_ALL = '00000002'X
+	PARAMETER PSCAN$M_BIT_ANY = '00000004'X
+	PARAMETER PSCAN$M_GEQ = '00000008'X
+	PARAMETER PSCAN$M_GTR = '00000010'X
+	PARAMETER PSCAN$M_LEQ = '00000020'X
+	PARAMETER PSCAN$M_LSS = '00000040'X
+	PARAMETER PSCAN$M_PREFIX_MATCH = '00000080'X
+	PARAMETER PSCAN$M_WILDCARD = '00000100'X
+	PARAMETER PSCAN$M_CASE_BLIND = '00000200'X
+	PARAMETER PSCAN$M_EQL = '00000400'X
+	PARAMETER PSCAN$M_NEQ = '00000800'X
+	STRUCTURE /item_specific_flags/
+	    PARAMETER PSCAN$S_OR = 1
+	    PARAMETER PSCAN$V_OR = 0
+	    PARAMETER PSCAN$S_BIT_ALL = 1
+	    PARAMETER PSCAN$V_BIT_ALL = 1
+	    PARAMETER PSCAN$S_BIT_ANY = 1
+	    PARAMETER PSCAN$V_BIT_ANY = 2
+	    PARAMETER PSCAN$S_GEQ = 1
+	    PARAMETER PSCAN$V_GEQ = 3
+	    PARAMETER PSCAN$S_GTR = 1
+	    PARAMETER PSCAN$V_GTR = 4
+	    PARAMETER PSCAN$S_LEQ = 1
+	    PARAMETER PSCAN$V_LEQ = 5
+	    PARAMETER PSCAN$S_LSS = 1
+	    PARAMETER PSCAN$V_LSS = 6
+	    PARAMETER PSCAN$S_PREFIX_MATCH = 1
+	    PARAMETER PSCAN$V_PREFIX_MATCH = 7
+	    PARAMETER PSCAN$S_WILDCARD = 1
+	    PARAMETER PSCAN$V_WILDCARD = 8
+	    PARAMETER PSCAN$S_CASE_BLIND = 1
+	    PARAMETER PSCAN$V_CASE_BLIND = 9
+	    PARAMETER PSCAN$S_EQL = 1
+	    PARAMETER PSCAN$V_EQL = 10
+	    PARAMETER PSCAN$S_NEQ = 1
+	    PARAMETER PSCAN$V_NEQ = 11
+	BYTE %FILL (2)
+	END STRUCTURE
+
+	CHARACTER USERNAME*(*),TERMINAL*(*)
+C
+C	Replace all the lines in this subroutine with the following if
+C	you are running V5.2 or older.
+C
+C	DATA CONTEXT/-1/
+C	CALL INIT_ITMLST	! Initialize item list
+C				! Now add items to list
+C	CALL ADD_2_ITMLST(LEN(USERNAME),JPI$_USERNAME,%LOC(USERNAME))
+C	CALL ADD_2_ITMLST(LEN(TERMINAL),JPI$_TERMINAL,%LOC(TERMINAL))
+C	CALL ADD_2_ITMLST(4,JPI$_MODE,%LOC(UJPIMODE))
+C	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+C	IER = 1
+C	UJPIMODE = -1
+C	TERMINAL(1:1) = CHAR(0)
+C	DO WHILE (IER.AND.(TERMINAL(1:1).EQ.CHAR(0)).AND.(UJPIMODE.NE.
+C     *            JPI$K_INTERACTIVE))
+C						! Get next interactive process
+C	   IER = SYS$GETJPIW(,CONTEXT,,%VAL(GETJPI_ITMLST),,,,)
+C						! Get next process.
+C	END DO
+C	IF (.NOT.IER) CONTEXT = -1
+C  	GETUSERS = IER
+
+	DATA CONTEXT/0/
+
+	IF (CONTEXT.EQ.0) THEN 
+	   CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	   CALL ADD_2_ITMLST_WITH_RET(0,PSCAN$_NODE_CSID,0,PSCAN$M_NEQ)
+	   CALL ADD_2_ITMLST(0,PSCAN$_MODE,JPI$K_INTERACTIVE)
+	   CALL END_ITMLST(PSCAN_ITMLST)	! Get address of itemlist
+
+	   IER = SYS$PROCESS_SCAN(CONTEXT,%VAL(PSCAN_ITMLST))
+	END IF
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(LEN(USERNAME),JPI$_USERNAME,%LOC(USERNAME))
+	CALL ADD_2_ITMLST(LEN(TERMINAL),JPI$_TERMINAL,%LOC(TERMINAL))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = 1
+	TERMINAL(:1) = CHAR(0)
+	DO WHILE (IER.AND.TERMINAL(:1).EQ.CHAR(0))
+						! Get next interactive process
+	   IER = SYS$GETJPIW(,CONTEXT,,%VAL(GETJPI_ITMLST),,,,)
+						! Get next process.
+	END DO
+
+	IF (.NOT.IER) CONTEXT = 0
+
+	GETUSERS = IER
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE OPEN_USERINFO
+C
+C  SUBROUTINE OPEN_USERINFO
+C
+C  FUNCTION:  Opens the file in SYS$LOGIN which contains user information.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+	DATA USERINFO_READ /.FALSE./
+
+	INTEGER TODAY_BTIM(2)
+
+	CALL OPEN_BULLINF_SHARED
+
+	READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,LAST
+	DO I=1,FOLDER_MAX
+	   DO J=1,2
+	      LAST_READ_BTIM(J,I) = LAST(J,I)
+	   END DO
+	END DO
+
+	IF (IER.EQ.0) THEN		! Check to see if dates all in future
+	   CALL SYS_BINTIM('-',TODAY_BTIM)	! Get today's date
+	   DO I=1,FOLDER_MAX
+	      DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,I),TODAY_BTIM)
+	      IF (DIFF.GE.0) THEN	! Must have been in a time wrap
+		 LAST_READ_BTIM(1,I) = TODAY_BTIM(1)
+		 LAST_READ_BTIM(2,I) = TODAY_BTIM(2)
+	      END IF
+	   END DO
+	END IF
+
+	IF (IER.NE.0.AND.TEST_BULLCP().EQ.2	! Is this BULLCP process?
+     &	    .AND.CONFIRM_USER(USERNAME).NE.0) THEN	! Not real user?
+	   USERNAME = 'DECNET'
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,LAST
+	   DO I=1,FOLDER_MAX
+	      DO J=1,2
+	         LAST_READ_BTIM(J,I) = LAST(J,I)
+	      END DO
+       	   END DO
+	END IF
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=10,FILE='SYS$LOGIN:BULLETIN.INF',STATUS='OLD',
+     &	      RECORDTYPE='FIXED',FORM='UNFORMATTED',IOSTAT=IER)
+	   INQUIRE(UNIT=10,RECORDSIZE=INF_SIZE)
+	   IF (IER.EQ.0) THEN
+	      READ (10)
+     &	  ((LAST_READ_BTIM(1,I),LAST_READ_BTIM(2,I)),I=1,INF_SIZE/2)
+	      CLOSE (UNIT=10,STATUS='DELETE')
+	   ELSE
+	      CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
+	      CALL READ_USER_FILE_KEYNAME(USERNAME,IER)  ! Find user's info
+	      IF (IER.NE.0.AND.TEST_BULLCP().EQ.2) THEN	! BULLCP process?
+	         CALL SYS_BINTIM('-',LOGIN_BTIM)	! Get today's date
+	         CALL SYS_BINTIM('5-NOV-1956 11:05:56',READ_BTIM)
+		 CALL READ_USER_FILE_HEADER(IER)
+		 NEW_FLAG(1) = 143
+		 NEW_FLAG(2) = 0
+	         CALL WRITE_USER_FILE_NEW(IER)
+	      END IF
+	      CALL CLOSE_BULLUSER
+	      IF (IER.EQ.0) THEN
+	         DO I=1,FOLDER_MAX
+	            LAST_READ_BTIM(1,I) = READ_BTIM(1)
+	            LAST_READ_BTIM(2,I) = READ_BTIM(2)
+	         END DO
+	      END IF
+	   END IF
+  	   DO I=1,FOLDER_MAX
+	      DO J=1,2
+	         LAST(J,I) = LAST_READ_BTIM(J,I)
+	      END DO
+	   END DO
+	   IF (IER.EQ.0) WRITE (9,IOSTAT=IER) USERNAME,LAST
+           DO WHILE (REC_LOCK(IER))
+              READ (9,KEY='*DEFAULT',IOSTAT=IER) TEMP_USER,INF_REC
+	   END DO
+           IF (IER.EQ.0) THEN
+	      LU = TRIM(USERNAME)
+	      USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	      IF (LU.GT.1) THEN
+	         USERNAME(LU-1:LU-1) =
+     &			CHAR(128.OR.ICHAR(USERNAME(LU-1:LU-1)))
+	      ELSE
+	         USERNAME(2:2) = CHAR(128.OR.ICHAR(USERNAME(2:2)))
+	      END IF
+	      WRITE (9,IOSTAT=IER) USERNAME,INF_REC
+	      USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	      IF (LU.GT.1) THEN
+	         USERNAME(LU-1:LU-1) =
+     &			CHAR(127.AND.ICHAR(USERNAME(LU-1:LU-1)))
+	      ELSE
+	         USERNAME(2:2) = CHAR(127.AND.ICHAR(USERNAME(2:2)))
+	      END IF
+	   END IF
+	END IF
+
+	LU = TRIM(USERNAME)
+	USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	READ (9,KEY=USERNAME,IOSTAT=IER1) USERNAME,LAST_SYS_BTIM
+	USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	IF (IER1.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      LAST_SYS_BTIM(1,I) = 0
+	      LAST_SYS_BTIM(2,I) = 0
+	   END DO
+	END IF
+
+	CALL READ_NEWS_USERINFO(USERNAME,IER)
+
+	CALL CLOSE_BULLINF
+
+	CALL LIB$MOVC3(FOLDER_MAX*2*4,LAST_READ_BTIM(1,1)
+     &				,OLD_LAST_READ_BTIM)
+	CALL LIB$MOVC3(FOLDER_MAX*2*4,LAST_SYS_BTIM,OLD_LAST_SYS_BTIM)
+	CALL LIB$MOVC3(FOLDER_MAX*2*4,LAST_NEWS_READ,OLD_LAST_NEWS_READ)
+
+	USERINFO_READ = .TRUE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_NEWS_USERINFO(NAME,IER)
+C
+C  SUBROUTINE READ_NEWS_USERINFO
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER*(*) NAME
+	 
+	LU = TRIM(NAME)
+
+	NAME(LU:LU) = CHAR(128.OR.ICHAR(NAME(LU:LU)))
+	IF (LU.GT.1) THEN
+	   NAME(LU-1:LU-1) = CHAR(128.OR.ICHAR(NAME(LU-1:LU-1)))
+	ELSE
+	   NAME(2:2) = CHAR(128.OR.ICHAR(NAME(2:2)))
+	END IF
+	READ (9,KEY=NAME,IOSTAT=IER) NAME,LAST_NEWS_READ
+	NAME(LU:LU) = CHAR(127.AND.ICHAR(NAME(LU:LU)))
+	IF (LU.GT.1) THEN
+	   NAME(LU-1:LU-1) = CHAR(127.AND.ICHAR(NAME(LU-1:LU-1)))
+	ELSE
+	   NAME(2:2) = CHAR(127.AND.ICHAR(NAME(2:2)))
+	END IF
+	IF (IER.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      LAST_NEWS_READ(1,I) = 0
+	      LAST_NEWS_READ(2,I) = 0
+	   END DO
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE UPDATE_USERINFO
+C
+C  SUBROUTINE UPDATE_USERINFO
+C
+C  FUNCTION:  Updates the latest message read times for each folder.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /USERINFO/ USERINFO_READ,OLD_LAST_READ_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_SYS_BTIM(2,FOLDER_MAX)
+	COMMON /USERINFO/ OLD_LAST_NEWS_READ(2,FOLDER_MAX)
+	COMMON /USERINFO/ LAST(2,FOLDER_MAX)
+	EQUIVALENCE (OLD_LAST_NEWS_READ2(1,1),OLD_LAST_NEWS_READ(1,1))
+	INTEGER*2 OLD_LAST_NEWS_READ2(4,FOLDER_MAX)
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /LAST_FOLDER/ LAST_FOLDER_NUMBER 
+
+	IF (.NOT.USERINFO_READ) RETURN
+
+	DIFF = .FALSE.
+	IF (REMOTE_SET.EQ.0.OR.REMOTE_SET.EQ.1) THEN 
+	   DIFF = (LAST_READ_BTIM(1,LAST_FOLDER_NUMBER+1).NE.
+     &		  OLD_LAST_READ_BTIM(1,LAST_FOLDER_NUMBER+1)).OR.
+     &		  (LAST_READ_BTIM(2,LAST_FOLDER_NUMBER+1).NE.
+     &		  OLD_LAST_READ_BTIM(2,LAST_FOLDER_NUMBER+1))
+	END IF
+
+	DIFF1 = .FALSE.
+	IF (REMOTE_SET.EQ.0.OR.REMOTE_SET.EQ.1) THEN 
+	   DIFF1 = (LAST_SYS_BTIM(1,LAST_FOLDER_NUMBER+1).NE.
+     &	      	   OLD_LAST_SYS_BTIM(1,LAST_FOLDER_NUMBER+1)).OR.
+     &	       	   (LAST_SYS_BTIM(2,LAST_FOLDER_NUMBER+1).NE.
+     &		   OLD_LAST_SYS_BTIM(2,LAST_FOLDER_NUMBER+1))
+	END IF
+
+	DIFF2 = .FALSE.
+        GO TO 10
+	
+	ENTRY UPDATE_USERINFO_NEWS_ALWAYS
+	DIFF2 = .TRUE.
+
+10	IF (.NOT.DIFF2) THEN
+  	   DO I=1,FOLDER_MAX
+	      DIFF2 = (LAST_NEWS_READ(1,I).NE.
+     &	      	   OLD_LAST_NEWS_READ(1,I)).OR.
+     &	       	   (LAST_NEWS_READ(2,I).NE.
+     &		   OLD_LAST_NEWS_READ(2,I)).OR.DIFF2
+	   END DO
+	END IF
+
+	IF (.NOT.(DIFF.OR.DIFF1.OR.DIFF2)) RETURN
+
+	CALL OPEN_BULLINF_SHARED
+
+	IF (DIFF) THEN
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,LAST
+	   IF (IER.EQ.0) THEN
+  	      DO I=1,FOLDER_MAX
+	         DO J=1,2
+		    IF (LAST_FOLDER_NUMBER+1.EQ.I)
+     &		       LAST(J,I) = LAST_READ_BTIM(J,I)
+		    LAST_READ_BTIM(J,I) = LAST(J,I)
+	         END DO
+	      END DO
+	      REWRITE (9,IOSTAT=IER) USERNAME,LAST
+	   END IF
+	END IF
+
+	IF (DIFF1) THEN
+	   LU = TRIM(USERNAME)
+	   USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,OLD_LAST_SYS_BTIM
+	   IF (IER.EQ.0) THEN
+  	      DO I=1,FOLDER_MAX
+	         DO J=1,2
+		    IF (LAST_FOLDER_NUMBER+1.EQ.I)
+     &			  OLD_LAST_SYS_BTIM(J,I) = LAST_SYS_BTIM(J,I)
+		    LAST_SYS_BTIM(J,I) = OLD_LAST_SYS_BTIM(J,I)
+	         END DO
+	      END DO
+	      REWRITE (9,IOSTAT=IER) USERNAME,OLD_LAST_SYS_BTIM
+	   ELSE
+	      WRITE (9,IOSTAT=IER) USERNAME,LAST_SYS_BTIM
+	   END IF
+	   USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	END IF
+
+	IF (DIFF2) THEN
+	   LU = TRIM(USERNAME)
+	   USERNAME(LU:LU) = CHAR(128.OR.ICHAR(USERNAME(LU:LU)))
+	   IF (LU.GT.1) THEN
+	      USERNAME(LU-1:LU-1) = CHAR(128.OR.ICHAR(USERNAME(LU-1:LU-1)))
+	   ELSE
+	      USERNAME(2:2) = CHAR(128.OR.ICHAR(USERNAME(2:2)))
+	   END IF
+	   READ (9,KEY=USERNAME,IOSTAT=IER) USERNAME,OLD_LAST_NEWS_READ
+	   IF (IER.EQ.0) THEN
+  	      DO I=1,FOLDER_MAX
+	         DO J=2,1,-1
+		    IF (I.EQ.NEWS_FIND_SUBSCRIBE().OR.
+     &			OLD_LAST_NEWS_READ2(1,I).NE.LAST_NEWS_READ2(1,I))
+     &		       OLD_LAST_NEWS_READ(J,I) = LAST_NEWS_READ(J,I)
+		    LAST_NEWS_READ(J,I) = OLD_LAST_NEWS_READ(J,I)
+	         END DO
+	      END DO
+	      REWRITE (9,IOSTAT=IER) USERNAME,OLD_LAST_NEWS_READ
+	   ELSE
+	      WRITE (9,IOSTAT=IER) USERNAME,LAST_NEWS_READ
+	   END IF
+	   USERNAME(LU:LU) = CHAR(127.AND.ICHAR(USERNAME(LU:LU)))
+	   IF (LU.GT.1) THEN
+	      USERNAME(LU-1:LU-1) = CHAR(127.AND.ICHAR(USERNAME(LU-1:LU-1)))
+	   ELSE
+	      USERNAME(2:2) = CHAR(127.AND.ICHAR(USERNAME(2:2)))
+	   END IF
+	END IF
+
+	CALL CLOSE_BULLINF
+
+	RETURN
+	END
+
+
+	INTEGER FUNCTION SYS_BINTIM(TIME,BTIM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INTEGER BTIM(2)
+
+	CHARACTER*(*) TIME
+
+	CHARACTER*24 TIME1
+
+	TIME1 = TIME(FIRST_ALPHA(TIME):)
+	DO I=TRIM(TIME1),2,-1
+	   IF (TIME1(I-1:I).EQ.'  ') TIME1(I-1:) = TIME1(I:)
+	END DO
+
+	IF (TIME1.EQ.'-') TIME1 = '-- :'
+
+	IF (TRIM(TIME1).EQ.20) THEN
+	   SYS_BINTIM = SYS$BINTIM(TIME1//'.00',BTIM)
+	ELSE
+	   SYS_BINTIM = SYS$BINTIM(TIME1(:MIN(TRIM(TIME1),23)),BTIM)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEW_MESSAGE_NOTIFICATION
+C
+C  SUBROUTINE NEW_MESSAGE_NOTIFICATION
+C
+C  FUNCTION:
+C
+C  Update user's last read bulletin date.  If new bulletins have been
+C  added since the last time bulletins have been read, position bulletin
+C  pointer so that next bulletin read is the first new bulletin, and
+C  alert user.  If READNEW set and no new bulletins, just exit.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /READIT/ READIT
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+	CHARACTER*4 SEPARATE
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+
+	COMMON /LOGIN_BTIM/ LOGIN_BTIM_SAVE(2)
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	IF (INCMD(:4).EQ.'SHOW') THEN
+	   CALL READ_IN_FOLDERS			! Read folder info
+	ELSE IF (.NOT.LOGIN_SWITCH) THEN
+	   LOGIN_BTIM_SAVE(1) = LOGIN_BTIM(1)
+	   LOGIN_BTIM_SAVE(2) = LOGIN_BTIM(2)
+	   CALL UPDATE_READ(0)			! Update login time
+	   CALL SHOW_NEW_VERSION
+	   IF (CLI$PRESENT('SELECT_FOLDER')) THEN
+	      CALL SELECT_FOLDER(.TRUE.,IER)
+	      IF (IER) RETURN
+	   END IF
+	   CALL READ_IN_FOLDERS			! Read folder info
+	ELSE
+	   LOGIN_SWITCH = .FALSE.		! So LOGIN_FOLDER entry doesn't
+	END IF					! think it's called via LOGIN
+
+	FOLDER_Q = SAVE_FOLDER_Q1
+
+	DO I = 1,SAVE_FOLDER_NUM
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   CALL CLR2(NEW_MSG,FOLDER_NUMBER)	! Clear new message flag
+	   IF (.NOT.TEST_BULLCP().AND.NODE_AREA.GT.0.AND.READIT.EQ.1
+     &	       .AND.TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+	      CALL SET2(NEW_MSG,FOLDER_NUMBER)
+	   ELSE IF (TEST2(SET_FLAG,FOLDER_NUMBER).OR.
+     &		TEST2(BRIEF_FLAG,FOLDER_NUMBER).OR.
+     &		(FOLDER_NUMBER.GT.0.AND.
+     &		TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND.READIT.EQ.1)) THEN
+	      IF (READIT.EQ.1.AND.SYSTEM_SWITCH.AND.
+     &		TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+	         DIFF = COMPARE_BTIM(SYSTEM_LOGIN_BTIM,
+     &					F_NEWEST_BTIM)
+	      ELSE
+	         DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+		 IF (DIFF.LT.0.AND.READIT.EQ.1) THEN
+		    IF (.NOT.TEST2(BRIEF_FLAG,FOLDER_NUMBER).OR.
+     &			.NOT.TEST2(SET_FLAG,FOLDER_NUMBER).OR.
+     &			NEW_FLAG(2).NE.-1) THEN
+	               DIFF = COMPARE_BTIM(LOGIN_BTIM_SAVE,F_NEWEST_BTIM)
+		    END IF
+		    IF (FOLDER_BBOARD(:2).EQ.'::'.AND.DIFF.GE.0) THEN
+			IER = MINUTE_DIFF(LOGIN_BTIM_SAVE,F_NEWEST_BTIM)
+			IF (IER.LE.15) DIFF = -1
+		    END IF
+		 END IF
+	      END IF
+	      IF (F_NBULL.GT.0.AND.(DIFF.LT.0.OR.(READIT.EQ.1.AND.
+     &		  BTEST(FOLDER_FLAG,7)))) THEN	    ! If new unread messages
+		 CALL SET2(NEW_MSG,FOLDER_NUMBER)   ! Set new message flag
+	      END IF
+	   END IF
+	END DO
+
+	FOLDER_Q = SAVE_FOLDER_Q1
+
+	IF (READIT.EQ.0) THEN 			! If not in READNEW mode
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   NEW_MESS = .FALSE.
+	   DO I = 1,SAVE_FOLDER_NUM-1
+	      CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      IF (TEST2(NEW_MSG,FOLDER_NUMBER)) THEN
+		 DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+		 IF (DIFF.LT.0) THEN		! Are there unread messages?
+		    DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_NOSYS_BTIM)
+		    IF (DIFF.GT.0) THEN		! Unread non-system messages?
+	               DIFF = COMPARE_BTIM(LOGIN_BTIM,F_NEWEST_BTIM)
+						! No. Unread system messages?
+		       IF (DIFF.GT.0) THEN	! No, update last read time.
+			  LAST_READ_BTIM(1,FOLDER_NUMBER+1) =
+     &						F_NEWEST_BTIM(1)
+			  LAST_READ_BTIM(2,FOLDER_NUMBER+1) =
+     &						F_NEWEST_BTIM(2)
+		       END IF
+		    END IF
+		    IF (DIFF.LT.0) THEN
+		       WRITE (6,'('' There are new messages in '',
+     &			   ''folder '',A)') FOLDER(:TRIM(FOLDER))
+		       NEW_MESS = .TRUE.
+		    END IF
+		 END IF
+	      END IF
+	   END DO
+	   CALL NEWS_NEW_NOTIFICATION(NEWS_MESS)
+	   IF (INCMD(:4).EQ.'SHOW') THEN
+	      SAVE_FOLDER_Q1 = 0
+	      RETURN
+	   END IF
+	   IF (NEW_MESS.OR.NEWS_MESS) THEN
+	      WRITE (6,'('' Type SELECT followed by foldername to'',
+     &			 '' read above messages.'')')
+	   END IF
+	   SAVE_FOLDER_Q1 = 0
+	   FOLDER_NUMBER = 0
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				F_NEWEST_BTIM)
+	   IF (DIFF.LT.0.AND.F_NBULL.GT.0) THEN
+	      CALL FIND_NEWEST_BULL	! See if there are new messages
+	      IF (BULL_POINT.NE.-1) THEN
+	        WRITE(6,'('' Type READ to read new '',A,'' messages.'')')
+     &		   FOLDER(:TRIM(FOLDER))
+		NEW_COUNT = F_NBULL - BULL_POINT
+		DIG = 0
+		DO WHILE (NEW_COUNT.GT.0)
+		   NEW_COUNT = NEW_COUNT / 10
+		   DIG = DIG + 1
+		END DO
+		WRITE(6,'('' There are '',I<DIG>,'' new messages.'')')
+     &			F_NBULL - BULL_POINT	! Alert user if new bulletins
+	      ELSE
+	        BULL_POINT = 0
+	        LAST_READ_BTIM(1,FOLDER_NUMBER+1) = F_NEWEST_BTIM(1)
+	        LAST_READ_BTIM(2,FOLDER_NUMBER+1) = F_NEWEST_BTIM(2)
+	      END IF
+	   END IF
+	ELSE				! READNEW mode.
+	   DO I = 1,SAVE_FOLDER_NUM
+	      CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	      IF (TEST2(NEW_MSG,FOLDER_NUMBER)) THEN
+		 CALL SELECT_FOLDER(.FALSE.,IER)
+		 IF (IER) THEN
+	           IF (SYSTEM_SWITCH.AND.
+     &		        TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) THEN
+	            DIFF = COMPARE_BTIM(SYSTEM_LOGIN_BTIM,F_NEWEST_BTIM)
+		   ELSE
+		    DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &					F_NEWEST_BTIM)
+		    IF (BTEST(FOLDER_FLAG,7)) DIFF = -1
+		    IF (DIFF.LT.0.AND.TEST2(BRIEF_FLAG,FOLDER_NUMBER)
+     &		       .AND.TEST2(SET_FLAG,FOLDER_NUMBER)) THEN
+		       IF (DIFF.LT.0) THEN
+		        IF (FOLDER_NUMBER.GT.0) CALL LOGIN_FOLDER
+	                IF (BULL_POINT.NE.-1.OR.NEW_FLAG(2).EQ.-1.OR.
+     &			   .NOT.TEST2(SYSTEM_FLAG,FOLDER_NUMBER))
+     &		        WRITE (6,'('' There are new messages in folder ''
+     &			  ,A)') FOLDER(:TRIM(FOLDER))
+		       ELSE
+		        WRITE (6,'('' There are new messages in folder ''
+     &			  ,A)') FOLDER(:TRIM(FOLDER))
+		       END IF
+		       DIFF = 0
+		    END IF
+		   END IF
+		   IF (DIFF.LT.0) THEN
+		    IF (FOLDER_NUMBER.GT.0) CALL LOGIN_FOLDER
+	            IF (BULL_POINT.NE.-1) THEN
+		     IF (.NOT.TEST2(BRIEF_FLAG,FOLDER_NUMBER)) THEN
+		       IF (USERNAME(:3).EQ.'MRL'.OR.USERNAME(:7).EQ.'DNELSON')
+     &		TYPE *,LOGIN_BTIM,READ_BTIM,NEW_FLAG,SET_FLAG,BRIEF_FLAG
+		       SAVE_BULL_POINT = BULL_POINT
+		       REDO = .TRUE.
+		       DO WHILE (REDO)
+		          REDO = .FALSE.
+		          CALL READNEW(REDO)
+			  IF (REDO) CALL REDISPLAY_DIRECTORY
+			  BULL_POINT = SAVE_BULL_POINT
+		       END DO
+		     END IF
+		    END IF
+		   END IF
+		 END IF
+	      END IF
+	   END DO
+	   CALL NEWS_NEW_NOTIFICATION(NEWS_MESS)
+	   CALL EXIT
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE READ_IN_FOLDERS
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM
+	DATA SAVE_FOLDER_Q1/0/
+
+	COMMON /READIT/ READIT
+
+	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),DUMMY(2)
+
+	COMMON /SHUTDOWN/ NODE_NUMBER,NODE_AREA
+	COMMON /SHUTDOWN/ SHUTDOWN_FLAG(FLONG)
+
+        COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
+        COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
+        COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
+        CHARACTER*4 SEPARATE
+ 
+	CALL INIT_QUEUE(SAVE_FOLDER_Q1,FOLDER_COM)
+	FOLDER_Q = SAVE_FOLDER_Q1
+
+	CALL OPEN_BULLFOLDER_SHARED		! Go find folders
+
+	SAVE_FOLDER_NUM = 0
+
+	FOLDER_NUMBER = 0
+	CALL READ_FOLDER_FILE_KEYNUM(FOLDER_NUMBER,IER)
+        IF (LOGIN_SWITCH) FOLDER_NAME = FOLDER
+	DO WHILE (IER.EQ.0)
+	   SAVE_FOLDER_NUM = SAVE_FOLDER_NUM + 1
+	   IF (.NOT.TEST_BULLCP().AND.NODE_AREA.GT.0.AND.READIT.EQ.1
+     &	       .AND.TEST2(SHUTDOWN_FLAG,FOLDER_NUMBER)) THEN
+	   ELSE IF ((NEW_FLAG(1).LT.142.OR.NEW_FLAG(1).GT.143).AND.
+     &	      TEST2(BRIEF_FLAG,FOLDER_NUMBER).AND.
+     &	      .NOT.TEST2(SET_FLAG,FOLDER_NUMBER)) THEN
+	      CALL CHANGE_FLAG_NOCMD(0,3)
+	      CALL SET_VERSION
+	   ELSE IF (TEST2(SET_FLAG,FOLDER_NUMBER).OR.
+     &		TEST2(BRIEF_FLAG,FOLDER_NUMBER).OR.
+     &		(FOLDER_NUMBER.GT.0.AND.(BTEST(FOLDER_FLAG,2).OR.
+     &		TEST2(SYSTEM_FLAG,FOLDER_NUMBER)).AND.READIT.EQ.1)) THEN
+C
+C  Unknown problem caused system folder flag in folder file to disappear
+C  so this tests to see if the flag has disappeared and resets if needed.
+C
+	      IF (TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND.
+     &		  .NOT.BTEST(FOLDER_FLAG,2)) THEN
+		 FOLDER_FLAG = IBSET(FOLDER_FLAG,2)
+	         CALL REWRITE_FOLDER_FILE(IER)
+	      ELSE IF (.NOT.TEST2(SYSTEM_FLAG,FOLDER_NUMBER).AND.
+     &		  BTEST(FOLDER_FLAG,2)) THEN
+		 INQUIRE (UNIT=4,OPENED=IER)
+		 CALL MODIFY_SYSTEM_LIST(IER)
+	      END IF
+	   END IF
+	   CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+	   CALL READ_FOLDER_FILE_KEYNUM_GT(FOLDER_NUMBER,IER)
+	END DO
+
+	CALL CLOSE_BULLFOLDER
+
+	FOLDER_Q = SAVE_FOLDER_Q1
+	CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE DISCONNECT_REMOTE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	WRITE (6,'('' ERROR: Connection to remote folder disconnected.'')')
+
+	FOLDER_NUMBER = 0
+
+	CALL SELECT_FOLDER(.FALSE.,IER)
+
+	WRITE (6,'('' Resetting to '',A,'' folder.'')')
+     &	   FOLDER(:TRIM(FOLDER))
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin8.for b/decus/vmslt98a/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..4fd882545fa0fc5019481e12489b175905d4ec0e
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin8.for
@@ -0,0 +1,2163 @@
+C
+C  BULLETIN8.FOR, Version 10/27/94
+C  Purpose: Contains subroutines for the BULLETIN utility program.
+C  Environment: VAX/VMS
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE START_DECNET
+
+	IMPLICIT INTEGER (A - Z)
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /NEWSHOST/ NEWS_GOT_HOST
+
+	COMMON /LISTEN/ LISTEN_CHAN,LISTEN_IOSB(4)
+	INTEGER*2 LISTEN_IOSB
+
+	CHARACTER NAMEDESC*12 /'BULLETIN1'/
+	CHARACTER NAMEDESC1*4 /'NNTP'/
+
+	DIMENSION NFBDESC(2)
+	LOGICAL*1 NFB(5)
+
+	EXTERNAL IO$_ACPCONTROL,LISTEN_AST
+
+	PARAMETER NFB$C_DECLNAME = '15'X
+
+	IF (CONFIRM_USER('DECNET').EQ.0) THEN
+	   CALL SETDEFAULT('DECNET')
+	END IF
+
+C	CALL SET_TIMER('02')
+
+	GATEWAY_ONLY = SYS_TRNLNM('BULL_NEWS_GATEWAY_ONLY','DEFINED')
+
+	NFBDESC(1) = 5
+	NFBDESC(2) = %LOC(NFB)
+
+	NFB(1) = NFB$C_DECLNAME
+
+	NEWS_GOT_HOST = NEWS_GETHOST()
+
+	IF (.NOT.GATEWAY_ONLY) THEN
+	   IER = SYS$CREMBX(%VAL(0),MBX_CHAN,%VAL(132),%VAL(528),,,
+     &                   'BULL_MBX')
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$ASSIGN('_NET:',DCL_CHAN,,'BULL_MBX') ! Assign net device
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$QIOW(,%VAL(DCL_CHAN),IO$_ACPCONTROL,,,,
+     &		  NFBDESC,NAMEDESC(:9),,,,)
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   CALL SYS$SETAST(%VAL(0))
+	   CALL READ_MBX(DCL_CHAN)
+	   CALL SYS$SETAST(%VAL(1))
+	END IF
+
+	IF (.NOT.SYS_TRNLNM('BULL_NO_NEWS_GATEWAY','DEFINED')) THEN
+	   IER = SYS$CREMBX(%VAL(0),MBX_CHAN1,%VAL(132),%VAL(528),,,
+     &                   'BULL_MBX1')
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$ASSIGN('_NET:',DCL_CHAN1,,'BULL_MBX1')
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   IER = SYS$QIOW(,%VAL(DCL_CHAN1),IO$_ACPCONTROL,,,,
+     &		NFBDESC,NAMEDESC1,,,,)
+	   IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	   IF (.NOT.IER) CALL EXIT
+
+	   CALL SYS$SETAST(%VAL(0))
+	   CALL READ_MBX(DCL_CHAN1)
+	   CALL SYS$SETAST(%VAL(1))
+	END IF
+
+	IF (SYS_TRNLNM('BULL_TCP_NEWS_GATEWAY','DEFINED')) THEN
+	   IF (NNTP_LISTEN(LISTEN_CHAN)) THEN
+	      CALL NNTP_ACCEPT_WAIT(LISTEN_CHAN,LISTEN_AST,LISTEN_IOSB)
+	   END IF
+	END IF
+
+	IF (GATEWAY_ONLY) CALL SYS$HIBER()
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE LISTEN_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /LISTEN/ LISTEN_CHAN,LISTEN_IOSB(4)
+	INTEGER*2 LISTEN_IOSB
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	COMMON /NEWSHOST/ NEWS_GOT_HOST
+
+	EXTERNAL NEWS_SOCKET_AST
+
+	INTEGER*2 ACCEPT_IOSB(4)
+
+	IF (LISTEN_IOSB(1)) THEN
+	   IER = NNTP_ACCEPT(LISTEN_CHAN,ACCEPT_CHAN,ACCEPT_IOSB)
+	   IF (IER) THEN
+	      UNIT_INDEX = 1
+	      DO WHILE (UNIT_INDEX.LE.MAXLINK.AND.UNITS(UNIT_INDEX).NE.0)
+	          UNIT_INDEX = UNIT_INDEX + 1
+	      END DO
+	      IF (UNIT_INDEX.LE.MAXLINK) THEN
+	         COUNT = COUNT + 1
+	         DEVS(UNIT_INDEX) = ACCEPT_CHAN
+		 UNITS(UNIT_INDEX) = ACCEPT_CHAN
+	         IER = NEWS_GOT_HOST.AND.NEWS_ASSIGN()
+	         IF (IER) THEN
+	            NNTP_CHANS(UNIT_INDEX) = NEWS_GET_CHAN()
+		    WRITE_IOSB(1,UNIT_INDEX) = 1
+		    IER = NEWS_SOCKET_BULLCP(0,
+     &			WRITE_IOSB(1,UNIT_INDEX),NEWS_SOCKET_AST,UNIT_INDEX)
+		    IF (IER.EQ.-1) CALL NEWS_SOCKET_AST(%VAL(UNIT_INDEX))
+	         END IF
+	         IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	      ELSE
+	         CALL SYS$DASSGN(%VAL(ACCEPT_CHAN))
+	      END IF
+	   ELSE IF (ACCEPT_CHAN.NE.-1) THEN
+	      CALL SYS$DASSGN(%VAL(ACCEPT_CHAN)) 
+	   END IF
+ 	END IF                                   
+
+	CALL REQUEUE_NNTP_ACCEPT_WAIT()
+	
+	RETURN
+	END
+
+
+
+	SUBROUTINE REQUEUE_NNTP_ACCEPT_WAIT()
+	
+	IMPLICIT INTEGER (A-Z) 
+
+	COMMON /LISTEN/ LISTEN_CHAN,LISTEN_IOSB(4)
+	INTEGER*2 LISTEN_IOSB
+
+	EXTERNAL LISTEN_AST
+
+	CALL NNTP_ACCEPT_WAIT(LISTEN_CHAN,LISTEN_AST,LISTEN_IOSB)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SETDEFAULT(USERNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($LNMDEF)'
+
+	INCLUDE '($PSLDEF)'
+
+	INCLUDE '($UAIDEF)'
+
+	CHARACTER DEFDIR*64,DEFDEV*16,USERNAME*(*),ACCOUNT*12
+	CHARACTER SYSLOGIN*72
+
+	INTEGER*2 UIC(2)
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(LEN(DEFDEV),UAI$_DEFDEV,%LOC(DEFDEV))
+	CALL ADD_2_ITMLST(LEN(DEFDIR),UAI$_DEFDIR,%LOC(DEFDIR))
+	CALL ADD_2_ITMLST(LEN(ACCOUNT),UAI$_ACCOUNT,%LOC(ACCOUNT))
+	CALL ADD_2_ITMLST(4,UAI$_UIC,%LOC(UIC))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	CALL SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+
+	CALL SETACC(ACCOUNT)
+	CALL SETUSER(USERNAME)
+	CALL SETUIC(INT(UIC(2)),INT(UIC(1)))
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST
+     &		(ICHAR(DEFDEV(:1)),LNM$_STRING,%LOC(DEFDEV(2:)))
+	CALL END_ITMLST(CRELNM_ITMLST)	! Get address of itemlist
+
+	CALL SYS$CRELNM(,'LNM$PROCESS','SYS$DISK',PSL$C_SUPER,
+     &						%VAL(CRELNM_ITMLST))
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	SYSLOGIN = 'SYS$DISK:'//DEFDIR(2:)
+	CALL ADD_2_ITMLST
+     &		(ICHAR(DEFDIR(:1))+9,LNM$_STRING,%LOC(SYSLOGIN))
+	CALL END_ITMLST(CRELNM_ITMLST)	! Get address of itemlist
+
+	CALL SYS$CRELNM(,'LNM$PROCESS','SYS$LOGIN',PSL$C_SUPER,
+     &						%VAL(CRELNM_ITMLST))
+
+	CALL SYS$SETDDIR(DEFDIR(2:ICHAR(DEFDIR(:1))+1),,)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_MBX(DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	EXTERNAL MBX_AST
+
+	EXTERNAL IO$_READVBLK
+
+	DATA MBX_EF/0/
+
+	IF (MBX_EF.EQ.0) CALL LIB$GET_EF(MBX_EF)
+
+	IF (DCL_CHAN_NUM.EQ.DCL_CHAN) THEN
+	   MBX_CHAN_NUM = MBX_CHAN
+	ELSE
+	   MBX_CHAN_NUM = MBX_CHAN1
+	END IF
+
+	IER = SYS$QIO(%VAL(MBX_EF),%VAL(MBX_CHAN_NUM),
+     &		IO$_READVBLK,MBX_IOSB,
+     &		MBX_AST,%VAL(DCL_CHAN_NUM),MBX_BUF,%VAL(132),,,,)
+	IF (.NOT.IER) CALL SYS_GETMSG(IER)
+	IF (.NOT.IER) CALL EXIT
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE MBX_AST(DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($MSGDEF)'
+
+	INCLUDE 'BULLUSER.INC'
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	INTEGER*2 MBXMSG,UNIT2
+
+	EQUIVALENCE (MBX_BUF(1),MBXMSG)
+
+	CHARACTER NODENAME*8,FROMNAME*12
+
+	IF (MBXMSG.EQ.MSG$_CONNECT.AND.MBX_IOSB(1)) THEN
+	   LNODE = 0
+	   DO WHILE (MBX_BUF(10+LNODE).NE.':')
+	      LNODE = LNODE + 1
+	      NODENAME(LNODE:LNODE) = CHAR(MBX_BUF(9+LNODE))
+	   END DO
+	   DO I=LNODE+1,LEN(NODENAME)
+	      NODENAME(I:I) = ' '
+	   END DO
+	   I = 10 + LNODE
+	   DO WHILE (MBX_BUF(I).NE.'=')
+	      I = I + 1
+	   END DO
+	   LUSER = 0
+	   DO WHILE (MBX_BUF(I+LUSER+1).NE.' '.AND.
+     &		     MBX_BUF(I+LUSER+1).NE.'/')
+	      LUSER = LUSER + 1
+	      USERNAME(LUSER:LUSER) = CHAR(MBX_BUF(I+LUSER))
+	   END DO
+	   DO I=LUSER+1,LEN(USERNAME)
+	      USERNAME(I:I) = ' '
+	   END DO
+	   FROMNAME = USERNAME
+	   CALL GET_PROXY_USERNAME(NODENAME,USERNAME)
+	   CALL BULL_CONNECT(NODENAME,USERNAME,FROMNAME,%LOC(DCL_CHAN_NUM))
+	ELSE IF ((MBXMSG.EQ.MSG$_INTMSG.OR.MBXMSG.EQ.MSG$_REJECT.OR.
+     &		 MBXMSG.EQ.MSG$_CONFIRM).AND.MBX_IOSB(1)) THEN
+	   CALL READ_MBX(%LOC(DCL_CHAN_NUM))
+	ELSE
+ 	   CALL LIB$MOVC3(2,MBX_BUF(3),UNIT2)
+	   UNIT_INDEX = 1
+	   DO WHILE (UNIT_INDEX.LE.MAXLINK.AND.UNITS(UNIT_INDEX).NE.UNIT2)
+	      UNIT_INDEX = UNIT_INDEX + 1
+	   END DO
+	   IF (UNIT_INDEX.LE.MAXLINK) CALL DISCONNECT(UNIT_INDEX)
+ 	   CALL READ_MBX(%LOC(DCL_CHAN_NUM))
+	END IF
+
+	RETURN
+ 	END
+
+
+
+
+	SUBROUTINE READ_CHAN(CHAN,UNIT_INDEX)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	EXTERNAL READ_AST
+
+	EXTERNAL IO$_READVBLK
+
+	IER = SYS$QIO(,%VAL(CHAN),IO$_READVBLK,
+     &	   READ_IOSB(1,UNIT_INDEX),READ_AST,
+     &	   %VAL(UNIT_INDEX),READ_BUF(1,UNIT_INDEX),%VAL(1024),,,,)
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE WRITE_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	CHARACTER*128 INPUT
+
+	EXTERNAL IO$_READVBLK,NEWS_READ_AST
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (.NOT.WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   CALL DISCONNECT(UNIT_INDEX)
+	ELSE IF (LEN_SAVE(UNIT_INDEX).GT.0) THEN
+	   LEN_SAVE(UNIT_INDEX) = LEN_SAVE(UNIT_INDEX) - 1
+	   IF (LEN_SAVE(UNIT_INDEX).EQ.0) THEN
+	      IF (REC_SAVE(UNIT_INDEX).EQ.128) THEN
+	         REC_SAVE(UNIT_INDEX) = 0
+	      ELSE
+	         RETURN
+	      END IF
+	   ELSE
+              CALL READ_QUEUE(%VAL(OUT_SAVE(UNIT_INDEX)),
+     &		OUT_SAVE(UNIT_INDEX),INPUT)
+	   END IF
+	   CALL WRITE_CHAN(REC_SAVE(UNIT_INDEX),INPUT,UNIT_INDEX,IER)
+	ELSE IF (NNTP_CHANS(UNIT_INDEX).NE.0) THEN
+	   IER = SYS$QIO(,%VAL(NNTP_CHANS(UNIT_INDEX)),
+     &	      IO$_READVBLK,WRITE_IOSB(1,UNIT_INDEX),NEWS_READ_AST,
+     &	      %VAL(UNIT_INDEX),WRITE_BUF(1,UNIT_INDEX),
+     &	      %VAL(1024),,,,)
+	   IF (IER.AND.WRITE_IOSB(1,UNIT_INDEX).NE.0) THEN
+	      IER = WRITE_IOSB(1,UNIT_INDEX)
+	   END IF
+	   IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE READ_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /ACTIVITY/ IO(MAXLINK),IO_SAVE(MAXLINK)
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	EXTERNAL NEWS_WRITE_AST
+
+	EXTERNAL IO$_WRITEVBLK
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (.NOT.READ_IOSB(1,UNIT_INDEX)) RETURN
+
+C	IO(UNIT_INDEX) = IO(UNIT_INDEX) + 1
+
+	CALL LIB$MOVC3(4,READ_BUF(1,UNIT_INDEX),CMD_TYPE)
+
+	IF ((CMD_TYPE.LT.1.OR.CMD_TYPE.GT.16).AND.
+     &	    READ_IOSB(2,UNIT_INDEX).EQ.0) THEN
+	   CALL DISCONNECT(UNIT_INDEX)
+	ELSE IF (CMD_TYPE.LT.1.OR.CMD_TYPE.GT.16) THEN
+	   CALL NEWS_SET_CHAN(NNTP_CHANS(UNIT_INDEX))
+	   IER = NEWS_WRITE_PACKET_BULLCP(0,
+     &			READ_IOSB(1,UNIT_INDEX),NEWS_WRITE_AST,UNIT_INDEX,
+     &			READ_BUF(1,UNIT_INDEX),READ_IOSB(2,UNIT_INDEX))
+	   IF (IER.AND.READ_IOSB(1,UNIT_INDEX).NE.0) THEN
+	      IER = READ_IOSB(1,UNIT_INDEX)
+	   END IF
+	   IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	ELSE
+	   CALL EXECUTE_COMMAND(UNIT_INDEX)
+	   CALL READ_CHAN(DEVS(UNIT_INDEX),UNIT_INDEX)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE NEWS_WRITE_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (READ_IOSB(1,UNIT_INDEX)) THEN
+	   CALL READ_CHAN(DEVS(UNIT_INDEX),UNIT_INDEX)
+	   RETURN
+	END IF
+
+	CALL DISCONNECT(UNIT_INDEX)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE NEWS_READ_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   NUM = WRITE_IOSB(2,UNIT_INDEX)
+	   CALL WRITE_CHAN_BUF(NUM,UNIT_INDEX,IER)
+	   IF (IER) RETURN
+	END IF
+
+	CALL DISCONNECT(UNIT_INDEX)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE WRITE_CHAN(NUM,OUTPUT,UNIT_INDEX,IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	CHARACTER*(*) OUTPUT
+
+	EXTERNAL IO$_WRITEVBLK, WRITE_AST
+
+	CALL LIB$MOVC3(NUM,%REF(OUTPUT),WRITE_BUF(1,UNIT_INDEX))
+
+	ENTRY WRITE_CHAN_BUF(NUM,UNIT_INDEX,IER)
+
+	IER = SYS$QIO(,%VAL(DEVS(UNIT_INDEX)),
+     &	   IO$_WRITEVBLK,WRITE_IOSB(1,UNIT_INDEX),WRITE_AST,
+     &	   %VAL(UNIT_INDEX),WRITE_BUF(1,UNIT_INDEX),%VAL(NUM),,,,)
+
+	IF (IER.AND.WRITE_IOSB(1,UNIT_INDEX).NE.0) THEN
+	   IER = WRITE_IOSB(1,UNIT_INDEX)
+	END IF
+
+	RETURN
+
+	END
+
+
+
+
+
+	SUBROUTINE BULL_CONNECT(NODENAME,USERNAME,FROMNAME,DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	CHARACTER*(*) USERNAME,FROMNAME
+
+	COMMON /NEWSHOST/ NEWS_GOT_HOST
+
+	EXTERNAL IO$_ACCESS,IO$M_ABORT,NEWS_SOCKET_AST
+	
+	IO_REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+
+	CALL CONNECT_ACCEPT(REJECT,CHAN,UNIT_INDEX,
+     &		NODENAME,USERNAME,FROMNAME,DCL_CHAN_NUM)
+
+	IF (REJECT.NE.IO_REJECT) THEN
+	   IF (DCL_CHAN_NUM.NE.DCL_CHAN) THEN
+	      IER = NEWS_GOT_HOST.AND.NEWS_ASSIGN()
+	      IF (IER) THEN
+	         NNTP_CHANS(UNIT_INDEX) = NEWS_GET_CHAN()
+		 WRITE_IOSB(1,UNIT_INDEX) = 1
+		 IER = NEWS_SOCKET_BULLCP(0,
+     &			WRITE_IOSB(1,UNIT_INDEX),NEWS_SOCKET_AST,UNIT_INDEX)
+		 IF (IER.EQ.-1) CALL NEWS_SOCKET_AST(%VAL(UNIT_INDEX))
+	      END IF
+	      IF (.NOT.IER) CALL DISCONNECT(UNIT_INDEX)
+	   ELSE
+	      CALL READ_CHAN(CHAN,UNIT_INDEX)
+	   END IF
+	END IF
+
+	CALL READ_MBX(DCL_CHAN_NUM)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE NEWS_SOCKET_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	EXTERNAL NEWS_CREATE_AST
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   CALL NEWS_SET_CHAN(NNTP_CHANS(UNIT_INDEX))
+	   IER = NEWS_CREATE_BULLCP(0,
+     &			WRITE_IOSB(1,UNIT_INDEX),NEWS_CREATE_AST,UNIT_INDEX)
+	   IF (IER) RETURN
+	END IF
+
+	CALL DISCONNECT(UNIT_INDEX)
+
+	RETURN
+	END
+
+
+ 
+	SUBROUTINE NEWS_CREATE_AST(ASTPRM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	UNIT_INDEX = %LOC(ASTPRM)
+
+	IF (WRITE_IOSB(1,UNIT_INDEX)) THEN
+	   CALL WRITE_AST(%VAL(UNIT_INDEX))
+	   CALL READ_CHAN(DEVS(UNIT_INDEX),UNIT_INDEX)
+	ELSE
+	   CALL DISCONNECT(UNIT_INDEX)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE CONNECT_ACCEPT(REJECT,CHAN,UNIT_INDEX,
+     &		NODENAME,USERNAME,FROMNAME,DCL_CHAN_NUM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /PROCBUF/ WRITE_IOSB(4,MAXLINK),WRITE_BUF(1024,MAXLINK)
+	INTEGER*2 WRITE_IOSB
+	LOGICAL*1 WRITE_BUF
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+	DATA COUNT /0/
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	COMMON /CHANNEL/ MBX_CHAN,DCL_CHAN,MBX_CHAN1,DCL_CHAN1
+
+	EXTERNAL IO$_ACCESS,IO$M_ABORT
+
+	CHARACTER*(*) USERNAME,FROMNAME,NODENAME
+
+	CHARACTER*100 NCBDESC
+
+	START_NCB = 7+MBX_BUF(5)
+
+	LEN_NCB = MBX_BUF(START_NCB-1)
+
+	CALL LIB$MOVC3(LEN_NCB,MBX_BUF(START_NCB),%REF(NCBDESC))
+
+	IF (COUNT.GT.MAXLINK) THEN
+	   REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+	   CHAN = DCL_CHAN_NUM
+	ELSE
+	   IF (DCL_CHAN_NUM.EQ.DCL_CHAN) THEN
+	      IER = SYS$ASSIGN('_NET:',DEV_CHAN,,'BULL_MBX')
+	   ELSE
+	      IER = SYS$ASSIGN('_NET:',DEV_CHAN,,'BULL_MBX1')
+	   END IF
+
+	   IF (IER) CALL GETDEVUNIT(DEV_CHAN,DEV_UNIT,IER)
+
+	   IF (IER) THEN
+	      CHAN = DEV_CHAN
+	      REJECT = %LOC(IO$_ACCESS)
+
+	      UNIT_INDEX = 1
+	      DO WHILE (UNIT_INDEX.LE.MAXLINK.AND.UNITS(UNIT_INDEX).NE.0)
+	          UNIT_INDEX = UNIT_INDEX + 1
+	      END DO
+	   ELSE
+	      CALL SYS$DASSGN(%VAL(DEV_CHAN))
+	   END IF
+
+	   IF (.NOT.IER.OR.UNIT_INDEX.GT.MAXLINK) THEN
+	      REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+	      CHAN = DCL_CHAN_NUM
+	   ELSE
+	      COUNT = COUNT + 1
+	      UNITS(UNIT_INDEX) = DEV_UNIT
+	      DEVS(UNIT_INDEX) = DEV_CHAN
+	      USER_SAVE(UNIT_INDEX) = USERNAME
+	      FROM_SAVE(UNIT_INDEX) = FROMNAME
+	      NODE_SAVE(UNIT_INDEX) = NODENAME
+	      FOLDER_NUM(UNIT_INDEX) = -1
+	      LEN_SAVE(UNIT_INDEX) = 0
+	      PRIV_SAVE(1,UNIT_INDEX) = 0
+	      PRIV_SAVE(2,UNIT_INDEX) = 0
+	   END IF
+	END IF
+
+	IER = SYS$QIOW(,%VAL(CHAN),%VAL(REJECT),MBX_IOSB,,,
+     &		,NCBDESC(:LEN_NCB),,,,)
+
+	IF (REJECT.EQ.%LOC(IO$_ACCESS).AND.
+     &		(.NOT.IER.OR..NOT.MBX_IOSB(1))) THEN
+	   REJECT = %LOC(IO$_ACCESS)+%LOC(IO$M_ABORT)
+	   COUNT = COUNT - 1
+	   DEVS(UNIT_INDEX) = 0
+	   UNITS(UNIT_INDEX) = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETDEVUNIT(CHAN,DEV_UNIT,IER)
+C
+C  SUBROUTINE GETDEVUNIT
+C
+C  FUNCTION:
+C	To get device unit number
+C  INPUT:
+C	CHAN - Channel number
+C  OUTPUT:
+C	DEV_UNIT - Device unit number
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($DVIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST(4,DVI$_UNIT,%LOC(DEV_UNIT))
+	CALL END_ITMLST(GETDVI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETDVIW(,%VAL(CHAN),,%VAL(GETDVI_ITMLST),,,,)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETDEVNAME(CHAN,DEV_NAME,DLEN,IER)
+C
+C  SUBROUTINE GETDEVMAME
+C
+C  FUNCTION:
+C	To get device name
+C  INPUT:
+C	CHAN - Channel number
+C  OUTPUT:
+C	DEV_NAME - Device name
+C	DLEN - Length of device name
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($DVIDEF)'
+
+	CHARACTER*(*) DEV_NAME
+
+	CALL INIT_ITMLST	! Initialize item list
+				! Now add items to list
+	CALL ADD_2_ITMLST_WITH_RET
+     &		(LEN(DEV_NAME),DVI$_DEVNAM,%LOC(DEV_NAME),%LOC(DLEN))
+	CALL END_ITMLST(GETDVI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETDVIW(,%VAL(CHAN),,%VAL(GETDVI_ITMLST),,,,)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE DISCONNECT(UNIT_INDEX)
+C
+C  SUBROUTINE DISCONNECT
+C
+C  FUNCTION: Disconnects channel and remove its entry from the lists.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /MBXBUF/ MBX_IOSB(4),MBX_BUF(132)	! Buffer area for
+	INTEGER*2 MBX_IOSB				! terminal QIO calls.
+	LOGICAL*1 MBX_BUF
+
+	COMMON /NNTP/ NNTP_CHANS(MAXLINK)
+
+	IF (UNITS(UNIT_INDEX).EQ.0) RETURN
+
+	CALL SYS$DASSGN(%VAL(DEVS(UNIT_INDEX)))
+
+	IF (NNTP_CHANS(UNIT_INDEX).EQ.0) THEN
+	   CALL UPDATE_REMOTE_USERINFO(UNIT_INDEX)
+	END IF
+
+	COUNT = COUNT - 1
+	DEVS(UNIT_INDEX) = 0
+	UNITS(UNIT_INDEX) = 0
+
+	IF (NNTP_CHANS(UNIT_INDEX).NE.0) THEN
+	   CALL NEWS_SET_CHAN(NNTP_CHANS(UNIT_INDEX))
+	   CALL NEWS_DISCONNECT
+	   NNTP_CHANS(UNIT_INDEX) = 0
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_TIMER(MIN)
+C
+C SUBROUTINE SET_TIMER
+C
+C FUNCTION: Wakes up every MIN minutes to check for idle connections
+C
+	IMPLICIT INTEGER (A-Z)
+	INTEGER TIMADR(2)			! Buffer containing time
+						! in desired system format.
+	CHARACTER MIN*(*)
+
+	EXTERNAL CHECK_CONNECTIONS
+
+	CALL LIB$GET_EF(WAITEFN)
+
+	IER=SYS$BINTIM('0 00:'//MIN//':00.00',TIMADR)
+
+	ENTRY RESET_TIMER
+
+	IER=SYS$SETIMR(%VAL(WAITEFN),TIMADR,CHECK_CONNECTIONS,)
+						! Set timer.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE CHECK_CONNECTIONS
+
+	IMPLICIT INTEGER (A-Z)
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /ACTIVITY/ IO(MAXLINK),IO_SAVE(MAXLINK)
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	IF (COUNT.GT.0) THEN
+	   DO UNIT_INDEX=1,MAXLINK
+	      IF (DEVS(UNIT_INDEX).NE.0.AND.
+     &		IO(UNIT_INDEX).EQ.IO_SAVE(UNIT_INDEX)) THEN
+	         CALL DISCONNECT(UNIT_INDEX)
+	      END IF
+	   END DO
+	END IF
+
+	CALL RESET_TIMER
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GET_USER_PRIV(USERNAME,PRIV)
+
+	IMPLICIT INTEGER (A-Z)
+
+	DIMENSION PRIV(2)
+
+	CHARACTER USERNAME*(*)
+
+	INCLUDE '($UAIDEF)'
+
+	INTEGER*2 UIC(2)
+
+	CALL INIT_ITMLST
+	CALL ADD_2_ITMLST(8,UAI$_PRIV,%LOC(PRIV))
+	CALL END_ITMLST(GETUAI_ITMLST)
+
+	IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+
+	IF (.NOT.IER) THEN
+	   USERNAME = 'DECNET'
+	   IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_PROXY_USERNAME(NODE,USERNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER NODE*(*),USERNAME*(*)
+
+	CHARACTER NETUAF*100,USERTEMP*12
+
+	COMMON /NETUAF/ NETUAF_QUEUE,NETUAF_NUM
+
+	LNODE = LEN(NODE)
+	LUSER = LEN(USERNAME)
+
+	NUM = 1
+	NENTRY = NETUAF_QUEUE
+
+	USERTEMP = 'DECNET'
+
+	DO WHILE (NUM.LE.NETUAF_NUM)
+	   NUM = NUM + 1
+	   CALL READ_QUEUE(%VAL(NENTRY),NENTRY,NETUAF)
+	   IF ((NETUAF(:1).EQ.'*'.OR.NETUAF(:LNODE).EQ.NODE).AND.
+     &	       (NETUAF(33:32+LUSER).EQ.USERNAME.OR.
+     &	       NETUAF(65:65).EQ.'*')) THEN
+	      IF (NETUAF(33:32+LUSER).EQ.USERNAME) THEN
+	         IF (NETUAF(65:65).NE.'*') USERNAME = NETUAF(65:)
+	         RETURN
+	      END IF
+	      IF (NETUAF(65:65).NE.'*') THEN
+		 USERTEMP = NETUAF(65:)
+	      ELSE
+	         USERTEMP = USERNAME
+	      END IF
+	   END IF
+	END DO
+
+	USERNAME = USERTEMP
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GET_PROXY_ACCOUNTS
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER NETUAF*656
+
+	COMMON /NETUAF/ NETUAF_QUEUE,NETUAF_NUM
+	DATA NETUAF_QUEUE/0/
+
+	CALL INIT_QUEUE(NETUAF_QUEUE,NETUAF(:100))
+
+	OPEN (UNIT=7,FILE='NETPROXY',DEFAULTFILE='SYS$SYSTEM:NETPROXY.DAT',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+
+	FORMAT = 0
+
+	IF (IER.NE.0) THEN
+	   OPEN (UNIT=7,FILE='NETUAF',DEFAULTFILE='SYS$SYSTEM:NETUAF.DAT',
+     &       ACCESS='KEYED',FORM='FORMATTED',ORGANIZATION='INDEXED',
+     &       STATUS='OLD',READONLY,SHARED,IOSTAT=IER)
+	   FORMAT = 1
+	END IF
+
+	NETUAF_NUM = 0
+	NENTRY = NETUAF_QUEUE
+	DO WHILE (IER.EQ.0)
+	   READ (7,'(Q,A)',IOSTAT=IER) NLEN,NETUAF
+	   IF (IER.EQ.0) THEN
+	      NETUAF_NUM = NETUAF_NUM + 1
+	      IF (FORMAT.EQ.0) THEN
+		 NETUAF = NETUAF(13:)
+		 NLEN = NLEN - 12
+		 DO WHILE (NETUAF(67:67).NE.CHAR(1).AND.NLEN.GT.64)
+		    SKIP = 4 + ICHAR(NETUAF(65:65))
+		    NETUAF(65:) = NETUAF(65+SKIP:)
+		    NLEN = NLEN - SKIP
+		 END DO
+		 IF (NLEN.GT.64) THEN
+		    ULEN = ICHAR(NETUAF(65:65))
+		    NETUAF(65:) = NETUAF(69:)
+		    DO I=65+ULEN,76
+		       NETUAF(I:I) = ' '
+		    END DO
+		 ELSE
+		    NETUAF(65:) = 'DECNET'
+		 END IF
+	      END IF
+              CALL WRITE_QUEUE(%VAL(NENTRY),NENTRY,NETUAF(:100))
+	   END IF
+	END DO
+
+	CLOSE (UNIT=7)
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE EXECUTE_COMMAND(UNIT_INDEX)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+        INCLUDE 'BULLFILES.INC'
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /READBUF/ READ_IOSB(4,MAXLINK),READ_BUF(1024,MAXLINK)
+	COMMON /READBUF/ DEVS(MAXLINK),UNITS(MAXLINK),COUNT
+	INTEGER*2 READ_IOSB
+	LOGICAL*1 READ_BUF
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	COMMON /ACCESS/ READ_ONLY
+	LOGICAL READ_ONLY
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BROAD_MESSAGE/ BMESSAGE,BLENGTH
+
+	PARAMETER BRDCST_LIMIT = 82*12 + 2 +2
+	CHARACTER*(BRDCST_LIMIT) BMESSAGE
+
+        COMMON /MAIN_FOLDER_DIRECTORY/ FOLDER1_DIRECTORY
+        CHARACTER*80 FOLDER1_DIRECTORY
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+        CHARACTER*80 FOLDER2_DIRECTORY
+
+	DIMENSION SCRATCH(MAXLINK),OUT_HEAD(MAXLINK)
+	DATA SCRATCH/MAXLINK*0/,OUT_HEAD/MAXLINK*0/
+
+	EXTERNAL SS$_NOSUCHNODE,SS$_NOSUCHOBJ
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	CHARACTER BUFFER*(FOLDER_RECORD+16),DESCRIP_TEMP*56
+	CHARACTER NODENAME*8,BULLCP_USER*12,INQUEUE*128
+
+	EQUIVALENCE (BUFFER,CMD_TYPE),(BUFFER,INQUEUE)
+
+	INTEGER BULLCP_PRIV(2)
+
+	CALL COPY2(BULLCP_PRIV,PROCPRIV)
+
+	ILEN = READ_IOSB(2,UNIT_INDEX)
+	CALL LIB$MOVC3(ILEN,READ_BUF(1,UNIT_INDEX),%REF(BUFFER))
+
+	REMOTE_SET = .FALSE.
+	REC_SAVE(UNIT_INDEX) = 0
+	USERNAME = USER_SAVE(UNIT_INDEX)
+	FOLDER = FOLDERNAME(UNIT_INDEX)
+	FOLDER_NUMBER = FOLDER_NUM(UNIT_INDEX)
+	FOLDER_FLAG = 0
+	NODENAME = NODE_SAVE(UNIT_INDEX)
+	CALL COPY2(PROCPRIV,PRIV_SAVE(1,UNIT_INDEX))
+
+	CALL INIT_QUEUE(OUT_HEAD(UNIT_INDEX),INQUEUE)
+
+	IF (CMD_TYPE.EQ.3.OR.CMD_TYPE.EQ.4.OR.(CMD_TYPE.GE.9.AND.
+     &	    CMD_TYPE.LE.11).OR.CMD_TYPE.EQ.15.OR.CMD_TYPE.EQ.1) THEN
+						! Do we need priv info?
+	   IF (PROCPRIV(1).EQ.0.AND.PROCPRIV(2).EQ.0) THEN
+	      CALL GET_USER_PRIV(USER_SAVE(UNIT_INDEX),
+     &		 PRIV_SAVE(1,UNIT_INDEX))
+	      USERNAME = USER_SAVE(UNIT_INDEX)	! If changed to DECNET
+	      CALL COPY2(PROCPRIV,PRIV_SAVE(1,UNIT_INDEX))
+	      IF ( (PROCPRIV(1).AND.NEEDPRIV(1)).EQ.0.AND.
+     &		   (PROCPRIV(2).AND.NEEDPRIV(2)).EQ.0) THEN
+		 CALL CHECK_BULLETIN_PRIV(USERNAME)
+		 CALL COPY2(PRIV_SAVE(1,UNIT_INDEX),PROCPRIV)
+	      END IF
+	   END IF
+	END IF
+
+	FOLDER2_DIRECTORY = FOLDER_DIRECTORY
+	IF (FOLDER_DIRECTORY.NE.FOLDER1_DIRECTORY.AND.
+     &		TRIM(FOLDER1_DIRECTORY).GT.0) THEN
+	   FOLDER_DIRECTORY = FOLDER1_DIRECTORY
+	   CALL ADD_DIRECTORIES
+	END IF
+
+	IF (CMD_TYPE.EQ.1.AND.BUFFER(ILEN:ILEN).EQ.'?') THEN
+	   IF (BUFFER(5:ILEN).EQ.'SYSTEM?') THEN
+	      CALL LIB$MOVC3(4,1,%REF(BUFFER(1:)))
+	      CALL WRITE_CHAN(4,BUFFER,UNIT_INDEX,IER1)
+	   ELSE 
+	      CALL LIB$MOVC3(4,0,%REF(BUFFER(1:)))
+	      CALL WRITE_CHAN(4,BUFFER,UNIT_INDEX,IER1)
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.1) THEN			! Select folder
+	   IF (BUFFER(ILEN:ILEN).EQ.'+') THEN
+	      SYSLOG = .TRUE.
+	      ILEN = ILEN - 1
+	   ELSE 
+	      SYSLOG = .FALSE.
+	   END IF
+	   FOLDER1 = BUFFER(5:ILEN)
+	   FOLDER_NUMBER = -2
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL LIB$MOVC3(4,IER,%REF(BUFFER(1:)))
+	   CALL LIB$MOVC3(4,READ_ONLY,%REF(BUFFER(5:)))
+	   IF (USERNAME.NE.'DECNET'.AND.IER) THEN
+	      CALL OPEN_USERINFO
+	      IF (USERNAME.EQ.'DECNET') THEN	! User wasn't real.
+	       USER_SAVE(UNIT_INDEX) = USERNAME
+	       CALL LIB$MOVC3(4,0,%REF(BUFFER(9:)))
+	       CALL LIB$MOVC3(4,0,%REF(BUFFER(13:)))
+	      ELSE
+	       CALL LIB$MOVC3(8,LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				%REF(BUFFER(9:)))
+	       LAST_SAVE(1,UNIT_INDEX) = LAST_READ_BTIM(1,FOLDER_NUMBER+1)
+	       LAST_SAVE(2,UNIT_INDEX) = LAST_READ_BTIM(2,FOLDER_NUMBER+1)
+	      END IF
+	   ELSE
+	      CALL LIB$MOVC3(4,0,%REF(BUFFER(9:)))
+	      CALL LIB$MOVC3(4,0,%REF(BUFFER(13:)))
+	   END IF
+	   LINFO = 16
+	   IF (SYSLOG) THEN
+	      LINFO = 24
+	      CALL LIB$MOVC3(8,LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &			       LAST_SYS_SAVE(1,UNIT_INDEX))
+	      CALL LIB$MOVC3(8,LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &				%REF(BUFFER(17:)))
+	      IF (LAST_SYS_SAVE(1,UNIT_INDEX).EQ.0) THEN
+	         CALL LIB$MOVC3(8,LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				  LAST_SYS_BTIM(1,FOLDER_NUMBER+1))
+	      END IF
+	   END IF
+	   BUFFER = BUFFER(:LINFO)//FOLDER_COM
+	   CALL WRITE_CHAN(LINFO+LEN(FOLDER_COM),BUFFER,UNIT_INDEX,IER1)
+	   IF (IER.AND.IER1) THEN
+	      IF (SYSLOG) THEN
+		 CALL SAVE_LAST_SYS_BTIM(UNIT_INDEX)
+	      ELSE
+		 LAST_SYS_SAVE(1,UNIT_INDEX) = 0
+		 LAST_SYS_SAVE(2,UNIT_INDEX) = 0
+	      END IF
+	      FOLDERNAME(UNIT_INDEX) = FOLDER
+	      FOLDER_NUM(UNIT_INDEX) = FOLDER_NUMBER
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.2) THEN		! Add message
+	   LEN_SAVE(UNIT_INDEX) = 0
+	   OUT_SAVE(UNIT_INDEX) = OUT_HEAD(UNIT_INDEX)
+	ELSE IF (CMD_TYPE.EQ.6) THEN		! Add message line
+	   LEN_SAVE(UNIT_INDEX) = LEN_SAVE(UNIT_INDEX) + 1
+	   CALL WRITE_QUEUE(%VAL(OUT_SAVE(UNIT_INDEX)),
+     &			OUT_SAVE(UNIT_INDEX),BUFFER(5:132))
+	ELSE IF (CMD_TYPE.EQ.3) THEN		! Add message entry
+	   FROM = USER_SAVE(UNIT_INDEX)
+	   IF (FROM.EQ.'DECNET') FROM = FROM_SAVE(UNIT_INDEX)
+	   CALL LIB$MOVC3(56,%REF(BUFFER(5:)),%REF(DESCRIP))
+	   P = LEN(DESCRIP) + 5
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXDATE))
+	   P = LEN(EXDATE) + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXTIME))
+	   P = LEN(EXTIME) + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),SYSTEM)
+	   P = 4 + P
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   IF (READ_ONLY.AND.
+     &		FOLDER_OWNER.NE.USERNAME.AND..NOT.SETPRV_PRIV()) THEN
+	      BUFFER = 'ERROR: Insufficient privileges to add message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   ELSE IF ((SYSTEM.AND.7).NE.0) THEN
+	      IF (FOLDER_NUMBER.GT.0.AND.IBCLR(SYSTEM,1).NE.0.AND.
+     &			.NOT.BTEST(FOLDER_FLAG,2)) THEN	! Test if SYSTEM folder
+		 SYSTEM = SYSTEM.AND.2
+	         CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      END IF
+	      IF ((SYSTEM.AND.7).NE.0.AND..NOT.SETPRV_PRIV()) THEN
+							! Priv test
+	         IF (F_EXPIRE_LIMIT.GT.0.AND..NOT.  ! Expiration limit present
+     &		     FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+	            SYSTEM = 0
+	            CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+		 ELSE					! Allow permanent if
+		    SYSTEM = SYSTEM.AND.2		! owner of folder
+	         END IF
+	      END IF
+	      IF (BTEST(SYSTEM,2)) THEN			! Shutdown?
+	         CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
+	         WRITE (EXTIME,'(I4)') NODE_NUMBER
+	         WRITE (EXTIME(7:),'(I4)') NODE_AREA
+	         DO I=1,11
+		    IF (EXTIME(I:I).EQ.' ') EXTIME(I:I) = '0'
+	         END DO
+	         EXTIME = EXTIME(1:2)//':'//EXTIME(3:4)//':'//
+     &			 EXTIME(7:8)//'.'//EXTIME(9:10)
+	      END IF
+	   END IF
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),BROAD)
+	   P = 4 + P
+	   IF (BROAD.AND..NOT.SETPRV_PRIV().AND..NOT.OPER_PRIV()) THEN
+	      BROAD = 0
+	   END IF
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),BELL)
+	   P = 4 + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),ALL)
+	   P = 4 + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),CLUSTER)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(0,IER)			! Get NBLOCK
+	   IF (IER.EQ.0) NBLOCK = 0		! If new file, NBLOCK is 0
+	   CALL OPEN_BULLFIL
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   LENGTH = LEN_SAVE(UNIT_INDEX)
+	   LEN_SAVE(UNIT_INDEX) = 0
+	   DO I=1,LENGTH
+	      CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	      WRITE (1'NBLOCK+I) INQUEUE
+	   END DO
+	   IF (BROAD) THEN
+	      CALL GET_BROADCAST_MESSAGE(BELL)
+	      CALL BROADCAST(ALL,CLUSTER)
+	   END IF
+	   CALL CLOSE_BULLFIL			! Finished adding bulletin
+	   IF (BTEST(FOLDER_FLAG,14)) FROM = 'ANONYMOUS'
+	   CALL ADD_ENTRY			! Add the new directory entry
+	   CALL UPDATE_FOLDER			! Update info in folder file
+	   CALL CLOSE_BULLDIR			! Totally finished with add
+	   IF (NEWS_FEED()) THEN 
+	      BULL_POINT = NBULL
+	      INCMD = 'COPY/ORIGINAL/LOCAL '//
+     &			FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,'<')+1
+     &			:INDEX(FOLDER_DESCRIP,'>')-1)
+	      CALL CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
+	      CALL MOVE(.FALSE.)
+	   END IF
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+
+	   CALL SAVE_LAST_READ_BTIM(UNIT_INDEX)
+
+	   IF (.NOT.BROAD) GO TO 1000
+
+100	   CALL GETUSER(BULLCP_USER)		! Get present username
+	   CALL OPEN_BULLUSER_SHARED		! Broadcast on other nodes
+	   TEMP_USER = ':'
+	   DO WHILE (TEMP_USER(:1).EQ.':')
+	      DO WHILE (REC_LOCK(IER))		 
+	         READ (4,KEYGT=TEMP_USER,IOSTAT=IER)
+     &		   TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+		 TEMP_USER = TEMP_USER(:TRIM(TEMP_USER))
+		 IF (IER.EQ.0.AND.
+     &		     (TEMP_USER(2:TRIM(TEMP_USER)).EQ.NODENAME
+     &		     .OR..NOT.TEST2(NEW_FLAG,FOLDER_NUMBER))
+     &		     .AND.TEMP_USER(:1).EQ.':') THEN
+		    IER1 = REC_LOCK(IER)	! Skip the node that
+		 END IF				! originated the message
+	      END DO
+	      IF (TEMP_USER(:1).NE.':') THEN
+		 CALL CLOSE_BULLUSER
+		 CALL SETUSER(BULLCP_USER)
+		 REMOTE_SET = .FALSE.
+	         CLOSE (UNIT=REMOTE_UNIT)
+		 GO TO 1000
+	      END IF
+	      CALL SETUSER(USERNAME)		! Reset to original username
+	      FOLDER1 = 'GENERAL'
+	      FOLDER1_BBOARD = ':'//TEMP_USER
+	      CALL CONNECT_REMOTE_FOLDER(READ_ONLY,IER)
+	      IF (IER.NE.0) THEN
+		 CALL ERRSNS(IDUMMY,IDUMMY,INODE)
+	         IF (INODE.EQ.%LOC(SS$_NOSUCHNODE).OR.
+     &		     INODE.EQ.%LOC(SS$_NOSUCHOBJ).OR.INODE.EQ.0) THEN
+		    DELETE (4)
+		 END IF
+	      ELSE
+		 IER = 0
+		 I = 1
+		 DO WHILE (IER.EQ.0.AND.I.LT.BLENGTH)
+		    WRITE (REMOTE_UNIT,'(4A)',IOSTAT=IER)
+     &			15,-1,I,BMESSAGE(I:MIN(BLENGTH,I+127))
+		    I = I + 128
+		 END DO
+		 IF (IER.EQ.0) WRITE (REMOTE_UNIT,'(5A)',IOSTAT=IER)
+     &			15,BLENGTH,BELL,ALL,CLUSTER
+	      END IF
+	   END DO
+	ELSE IF (CMD_TYPE.EQ.8) THEN		! Read directory entry
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),ICOUNT)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR_SHARED
+	   IF (ICOUNT.GE.0) THEN
+	      CALL READDIR(ICOUNT,IER)
+	   ELSE
+	      CALL LIB$MOVC3(8,%REF(BUFFER(9:)),%REF(MSG_KEY(1:)))
+	      CALL READDIR_KEYGE(IER)
+	   END IF
+	   CALL CLOSE_BULLDIR
+	   CALL LIB$MOVC3(4,IER,%REF(BUFFER(1:)))
+	   IF (ICOUNT.NE.0) THEN
+	      BUFFER(5:) = BULLDIR_ENTRY
+	      CALL WRITE_CHAN
+     &		(LEN(BULLDIR_ENTRY)+4,BUFFER,UNIT_INDEX,IER)
+	   ELSE
+	      BUFFER(5:) = BULLDIR_HEADER
+	      CALL WRITE_CHAN
+     &		(LEN(BULLDIR_HEADER)+4,BUFFER,UNIT_INDEX,IER)
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.13) THEN		! Read directory entry
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),SBULL)
+	   CALL LIB$MOVC3(4,%REF(BUFFER(9:)),EBULL)
+	   CALL SET_FOLDER_FILE(0)
+  	   CALL OPEN_BULLDIR_SHARED
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   DO I=SBULL,EBULL,ISIGN(1,EBULL-SBULL)
+	      CALL READDIR(I,IER)
+	      INQUEUE = BULLDIR_ENTRY
+              CALL WRITE_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   END DO
+	   CALL CLOSE_BULLDIR
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   REC_SAVE(UNIT_INDEX) = LEN(BULLDIR_ENTRY)
+	   LEN_SAVE(UNIT_INDEX) = ABS(EBULL - SBULL) + 1
+           CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   OUT_SAVE(UNIT_INDEX) = OENTRY
+	   CALL WRITE_CHAN(REC_SAVE(UNIT_INDEX),INQUEUE,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.9) THEN		! Write directory entry
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),ICOUNT)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR
+	   IF (ICOUNT.GT.0) THEN
+	      BULLDIR_ENTRY = BUFFER(9:)
+	      CALL WRITEDIR_NOCONV(ICOUNT,IER)
+	   ELSE
+	      BULLDIR_HEADER = BUFFER(9:)
+	      CALL WRITEDIR_NOCONV(ICOUNT,IER)
+	   END IF
+	   CALL CLOSE_BULLDIR
+	ELSE IF (CMD_TYPE.EQ.4) THEN
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),BULL_DELETE)
+	   CALL LIB$MOVC3(4,%REF(BUFFER(9:)),IMMEDIATE)
+	   DESCRIP_TEMP = BUFFER(13:ILEN)
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(BULL_DELETE,IER)
+	   IF (IER.EQ.BULL_DELETE.OR.DESCRIP.NE.DESCRIP_TEMP) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Cannot find message to delete.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   ELSE IF (USERNAME.NE.FROM.AND.FROM_SAVE(UNIT_INDEX).NE.FROM
+     &	    .AND.FOLDER_OWNER.NE.USERNAME.AND..NOT.SETPRV_PRIV()) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Insufficient privileges to delete message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL REMOVE_ENTRY
+     &		(BULL_DELETE,BULL_DELETE,BULL_DELETE,IMMEDIATE)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.5) THEN		! Read message
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),ICOUNT)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(ICOUNT,IER)
+	   CALL OPEN_BULLFIL_SHARED
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   DO I=BLOCK,BLOCK+LENGTH-1
+	      READ (1'I,IOSTAT=IER) INQUEUE
+              CALL WRITE_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   END DO
+	   CALL CLOSE_BULLFIL
+	   CALL CLOSE_BULLDIR
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   REC_SAVE(UNIT_INDEX) = 128
+	   LEN_SAVE(UNIT_INDEX) = LENGTH
+           CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	   OUT_SAVE(UNIT_INDEX) = OENTRY
+	   CALL WRITE_CHAN(REC_SAVE(UNIT_INDEX),INQUEUE,UNIT_INDEX,IER)
+	   CALL SAVE_LAST_READ_BTIM(UNIT_INDEX)
+	ELSE IF (CMD_TYPE.EQ.10) THEN		! Replacing bulletin
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR
+	   CALL LIB$MOVC3(56,%REF(BUFFER(5:)),%REF(DESCRIP_TEMP))
+	   P = LEN(DESCRIP_TEMP) + 5
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),ICOUNT)
+	   P = 4 + P
+	   CALL READDIR(ICOUNT,IER)
+	   IF (IER.EQ.ICOUNT.OR.DESCRIP_TEMP.NE.DESCRIP) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Cannot find message to replace.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL LIB$MOVC3(56,%REF(BUFFER(P:)),%REF(DESCRIP))
+	   P = LEN(DESCRIP) + P
+	   CALL LIB$MOVC3(4,%REF(BUFFER(P:)),%REF(MSGTYPE))
+	   P = 4 + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXDATE))
+	   P = LEN(EXDATE) + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXTIME))
+	   P = LEN(EXTIME) + P
+	   ALLOW = (FOLDER_OWNER.EQ.USERNAME).OR.SETPRV_PRIV()
+	   IF ((FOLDER_NUMBER.GT.0.AND.(BTEST(MSGTYPE,0).OR.
+     &		BTEST(MSGTYPE,2)).AND..NOT.BTEST(FOLDER_FLAG,2)).OR.
+     &		(USERNAME.NE.FROM.AND..NOT.ALLOW).OR.
+     &		((MSGTYPE.AND..NOT.8).NE.0.AND..NOT.ALLOW)) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Insufficient privileges to replace message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL READDIR(0,IER)			! Get NBLOCK
+	   CALL OPEN_BULLFIL
+	   NEW_LENGTH = LEN_SAVE(UNIT_INDEX)
+	   LEN_SAVE(UNIT_INDEX) = 0
+	   OENTRY = OUT_HEAD(UNIT_INDEX)
+	   DO I=1,NEW_LENGTH
+	      CALL READ_QUEUE(%VAL(OENTRY),OENTRY,INQUEUE)
+	      WRITE (1'NBLOCK+I) INQUEUE
+	   END DO
+	   CALL CLOSE_BULLFIL			! Finished adding bulletin
+	   IF (NEW_LENGTH.GT.0) THEN
+	      NEMPTY = NEMPTY + LENGTH
+	      LENGTH = NEW_LENGTH
+	      BLOCK = NBLOCK + 1
+	   END IF
+	   CALL WRITEDIR(ICOUNT,IER)
+	   NBLOCK = NBLOCK + NEW_LENGTH
+	   CALL WRITEDIR(0,IER)
+	   CALL UPDATE_DIR_HEADER(BTEST(MSGTYPE,3),BTEST(MSGTYPE,1),
+     &		BTEST(MSGTYPE,2),EXDATE,EXTIME)
+	   IF (BTEST(MSGTYPE,0)) THEN
+	      SYSTEM = IBSET(SYSTEM,0)		! System?
+	   ELSE
+	      SYSTEM = IBCLR(SYSTEM,0)		! General?
+	   END IF
+	   CALL WRITEDIR(ICOUNT,IER)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.11) THEN		! Undeleting
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),BULL_DELETE)
+	   P = 4 + P
+	   CALL LIB$MOVC3(56,%REF(BUFFER(P:)),%REF(DESCRIP_TEMP))
+	   P = LEN(DESCRIP_TEMP) + P
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL OPEN_BULLDIR
+	   CALL READDIR(BULL_DELETE,IER)
+	   IF (IER.EQ.BULL_DELETE.OR.DESCRIP.NE.DESCRIP_TEMP) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Cannot find message to undelete.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   ELSE IF (USERNAME.NE.FROM.AND.FROM_SAVE(UNIT_INDEX).NE.FROM
+     &	    .AND.FOLDER_OWNER.NE.USERNAME.AND..NOT.SETPRV_PRIV()) THEN
+	      CALL CLOSE_BULLDIR
+	      BUFFER = 'ERROR: Insufficient privileges to undelete message.'
+	      CALL WRITE_CHAN(TRIM(BUFFER),BUFFER,UNIT_INDEX,IER)
+	      GO TO 1000
+	   END IF
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXDATE))
+	   P = LEN(EXDATE) + P
+	   CALL LIB$MOVC3(12,%REF(BUFFER(P:)),%REF(EXTIME))
+	   P = LEN(EXTIME) + P
+	   CALL WRITEDIR(BULL_DELETE,IER)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(LEN(FOLDER_COM),FOLDER_COM,UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.12) THEN		! Find newest bulletin
+	   CALL SET_FOLDER_FILE(0)
+	   CALL OPEN_BULLDIR_SHARED
+	   CALL READDIR(0,IER)
+	   CALL GET_NEWEST_MSG(%REF(BUFFER(5:)),BULL_POINT)
+	   CALL CLOSE_BULLDIR
+	   CALL WRITE_CHAN(4,%DESCR(BULL_POINT),UNIT_INDEX,IER)
+	ELSE IF (CMD_TYPE.EQ.14) THEN		! Register remote folder
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),FLAG)
+	   FOLDER1 = FOLDER
+	   FOLDER_NUMBER = -1
+	   CALL SELECT_FOLDER(.FALSE.,IER)
+	   CALL OPEN_BULLUSER_SHARED
+	   TEMP_USER = ':'//NODENAME(:TRIM(NODENAME))
+	   DO WHILE (REC_LOCK(IER))
+	      READ (4,KEY=TEMP_USER,IOSTAT=IER) 
+     &		TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG
+	   END DO
+	   IF (IER.NE.0) THEN
+	      DO I=1,FLONG
+		 NEW_FLAG (I) = 0
+	      END DO
+	   END IF
+	   IF (FLAG) THEN
+	      CALL SET2(NEW_FLAG,FOLDER_NUMBER)
+	   ELSE
+	      CALL CLR2(NEW_FLAG,FOLDER_NUMBER)
+	   END IF
+	   IF (IER.EQ.0) THEN
+	      REWRITE (4) TEMP_USER,
+     &				LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+	   ELSE
+	      TEMP_USER =  ':'//NODENAME(:TRIM(NODENAME))
+	      WRITE (4) TEMP_USER,
+     &				LOGIN_BTIM,READ_BTIM,NEW_FLAG,USERNAME
+	   END IF
+	   CALL CLOSE_BULLUSER
+	ELSE IF (CMD_TYPE.EQ.15) THEN		! Broadcast message
+	   CALL LIB$MOVC3(4,%REF(BUFFER(5:)),BLENGTH)
+	   CALL LIB$MOVC3(4,%REF(BUFFER(9:)),START)
+	   IF (BLENGTH.EQ.-1) THEN
+	      IF (SCRATCH(UNIT_INDEX).EQ.0) THEN
+		 CALL LIB$GET_VM(BRDCST_LIMIT,SCRATCH(UNIT_INDEX))
+	      END IF
+	      CALL LIB$MOVC3(ILEN-12,%REF(BUFFER(13:)),
+     &				%VAL(SCRATCH(UNIT_INDEX)+START-1))
+	   ELSE
+	      CALL LIB$MOVC3(BLENGTH,%VAL(SCRATCH(UNIT_INDEX)),
+     &				%REF(BMESSAGE(1:)))
+	      CALL LIB$MOVC3(4,%REF(BUFFER(13:)),ALL)
+	      CALL LIB$MOVC3(4,%REF(BUFFER(17:)),CLUSTER)
+	      CALL LIB$FREE_VM(BRDCST_LIMIT,SCRATCH(UNIT_INDEX))
+	      IF (ILEN.GT.20) THEN
+	         CALL LIB$MOVC3(4,%REF(BUFFER(21:)),FOLDER_NUMBER)
+	         FOLDER = BUFFER(44:)
+		 GO TO 100
+	      ELSE IF (SETPRV_PRIV().OR.OPER_PRIV()) THEN
+	         CALL BROADCAST(ALL,CLUSTER)
+	      END IF
+	   END IF
+	ELSE IF (CMD_TYPE.EQ.16) THEN		! Change folder nodename
+ 	   CALL OPEN_BULLFOLDER_SHARED
+	   IER = 0
+	   DO WHILE (IER.EQ.0)
+	      CALL READ_FOLDER_FILE(IER)
+	      IF ('::'//BUFFER(5:TRIM(BUFFER(:12))).EQ.
+     &		  FOLDER_BBOARD(:TRIM(BUFFER(:12))+2).AND.IER.EQ.0) THEN
+	         FOLDER_BBOARD(3:) = BUFFER(13:TRIM(BUFFER(:20)))
+	         CALL REWRITE_FOLDER_FILE(IER)
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLFOLDER
+	END IF
+
+1000	CALL COPY2(PROCPRIV,BULLCP_PRIV)
+
+	IF (FOLDER_DIRECTORY.NE.FOLDER2_DIRECTORY) THEN
+	   FOLDER_DIRECTORY = FOLDER2_DIRECTORY
+	   CALL ADD_DIRECTORIES
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE UPDATE_REMOTE_USERINFO(UNIT_INDEX)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	PARAMETER MAXLINK = 20
+
+	COMMON /CONNECT_STATUS/ FOLDER_NUM(MAXLINK),OUT_NUM(MAXLINK)
+	COMMON /CONNECT_STATUS/ USER_SAVE(MAXLINK),FOLDERNAME(MAXLINK)
+	COMMON /CONNECT_STATUS/ FROM_SAVE(MAXLINK),PRIV_SAVE(2,MAXLINK)
+	COMMON /CONNECT_STATUS/ NODE_SAVE(MAXLINK),OUT_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ REC_SAVE(MAXLINK),LEN_SAVE(MAXLINK)
+	COMMON /CONNECT_STATUS/ LAST_SAVE(2,MAXLINK),LAST_SYS_SAVE(2,MAXLINK)
+	CHARACTER USER_SAVE*12,FOLDERNAME*44,FROM_SAVE*12,NODE_SAVE*12
+
+	DIMENSION SAVE_BTIM(2)
+
+	USERNAME = USER_SAVE(UNIT_INDEX)
+	FOLDER_NUMBER = FOLDER_NUM(UNIT_INDEX)
+
+	IF (USERNAME.EQ.'DECNET'.OR.FOLDER_NUMBER.LT.0) RETURN
+
+	CALL OPEN_USERINFO
+	DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
+     &				LAST_SAVE(1,UNIT_INDEX))
+	IF (DIFF.LT.0) THEN
+	   LAST_READ_BTIM(1,FOLDER_NUMBER+1) = LAST_SAVE(1,UNIT_INDEX)
+	   LAST_READ_BTIM(2,FOLDER_NUMBER+1) = LAST_SAVE(2,UNIT_INDEX)
+	END IF
+
+	IF (LAST_SYS_BTIM(1,FOLDER_NUMBER+1).EQ.0.AND.
+     &	    LAST_SYS_BTIM(2,FOLDER_NUMBER+1).EQ.0.AND.
+     &	    LAST_SYS_SAVE(1,UNIT_INDEX).NE.0.AND.
+     &	    LAST_SYS_SAVE(2,UNIT_INDEX).NE.0) THEN
+ 	   DIFF1 = -1
+	ELSE IF (LAST_SYS_SAVE(1,UNIT_INDEX).NE.0.AND.
+     &	    LAST_SYS_SAVE(2,UNIT_INDEX).NE.0) THEN
+	   DIFF1 = COMPARE_BTIM(LAST_SYS_BTIM(1,FOLDER_NUMBER+1),
+     &				LAST_SYS_SAVE(1,UNIT_INDEX))
+	ELSE
+	   DIFF1 = 0
+	END IF
+
+	IF (DIFF1.LT.0) THEN
+	   LAST_SYS_BTIM(1,FOLDER_NUMBER+1) = LAST_SYS_SAVE(1,UNIT_INDEX)
+	   LAST_SYS_BTIM(2,FOLDER_NUMBER+1) = LAST_SYS_SAVE(2,UNIT_INDEX)
+	END IF
+
+	IF (DIFF1.LT.0.OR.DIFF.LT.0) CALL UPDATE_USERINFO
+
+	RETURN
+
+	ENTRY SAVE_LAST_READ_BTIM(UNIT_INDEX)
+
+	CALL SYS_BINTIM(DATE//' '//TIME,SAVE_BTIM)
+
+	DIFF = COMPARE_BTIM(LAST_SAVE(1,UNIT_INDEX),SAVE_BTIM)
+
+	IF (DIFF.GE.0) RETURN
+
+	LAST_SAVE(1,UNIT_INDEX) = SAVE_BTIM(1)
+	LAST_SAVE(2,UNIT_INDEX) = SAVE_BTIM(2)
+
+	RETURN
+
+	ENTRY SAVE_LAST_SYS_BTIM(UNIT_INDEX)
+
+	CALL SYS_BINTIM('-',SAVE_BTIM)			! Get today's date
+
+	LAST_SYS_SAVE(1,UNIT_INDEX) = SAVE_BTIM(1)
+	LAST_SYS_SAVE(2,UNIT_INDEX) = SAVE_BTIM(2)
+
+	RETURN
+
+	END
+
+
+
+
+	SUBROUTINE CHECK_BULLETIN_PRIV(USERNAME)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
+
+	INCLUDE 'BULLFILES.INC'
+
+	IER = SETPRV_PRIV()
+
+	IF ((PROCPRIV(1).AND.NEEDPRIV(1)).EQ.0.AND.
+     &	    (PROCPRIV(2).AND.NEEDPRIV(2)).EQ.0) THEN
+	   CALL CHECK_ACCESS(BULLUSER_FILE(:TRIM(BULLUSER_FILE)),
+     &		USERNAME,R_ACCESS,W_ACCESS)
+	   IF (R_ACCESS) CALL COPY2(PROCPRIV,NEEDPRIV)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE GETACC(ACCOUNT)
+C
+C  SUBROUTINE GETACC
+C
+C  FUNCTION:
+C	To get account of present process.
+C  OUTPUTS:
+C	ACCOUNT   -   ACCOUNT owner of present process.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) ACCOUNT		! Limit is 12 characters
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(LEN(ACCOUNT),JPI$_ACCOUNT,%LOC(ACCOUNT))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE GETSTS(STS)
+C
+C  SUBROUTINE GETSTS
+C
+C  FUNCTION:
+C	To get status of present process. This tells if its a batch process.
+C  OUTPUTS:
+C	STS   -   Status word of present process.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($JPIDEF)'
+
+	CALL INIT_ITMLST	! Initialize item list
+	CALL ADD_2_ITMLST(4,JPI$_STS,%LOC(STS))
+	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist
+
+	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info
+
+	RETURN
+	END
+
+
+
+
+
+	INTEGER FUNCTION LNM_MODE_EXEC(FAB,RAB,LUN)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($FABDEF)'
+	INCLUDE '($RABDEF)'
+
+	RECORD /FABDEF/ FAB
+	RECORD /RABDEF/ RAB
+
+	FAB.FAB$B_ACMODES = ISHFT(1,FAB$V_LNM_MODE)
+
+	STATUS = SYS$OPEN(FAB)
+	IF (STATUS) STATUS = SYS$CONNECT(RAB)
+
+	LNM_MODE_EXEC = STATUS
+
+	END
+
+
+
+	INTEGER FUNCTION REC_LOCK(IER)
+
+	INCLUDE '($FORIOSDEF)'
+
+	DATA INIT /.TRUE./
+
+	IF (INIT) THEN
+	   REC_LOCK = 1
+	   INIT = .FALSE.
+	ELSE
+	   IF (IER.EQ.FOR$IOS_SPERECLOC) THEN
+	      CALL WAIT_SEC('01')
+	      INIT = INIT + 2
+	      IF (INIT.GT.60) THEN
+		 WRITE (6,'('' Bulletin aborting due to record lock'',
+     &			    '' problem.  Alert system administrator.'')')
+		 CALL EXIT
+	      END IF
+	   ELSE
+	      REC_LOCK = 0
+	      INIT = .TRUE.
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+	INTEGER FUNCTION TRIM(INPUT)
+	CHARACTER*(*) INPUT
+	DO TRIM=LEN(INPUT),1,-1
+	 IF (INPUT(TRIM:TRIM).NE.' '.AND.INPUT(TRIM:TRIM).NE.CHAR(0)) RETURN
+	END DO
+	RETURN
+	END
+
+	SUBROUTINE SYS_GETMSG(IER)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /WINDOW/ WINDOW
+
+	CHARACTER*80 MESSAGE
+
+	WINDOW = 1
+	CALL LIB$SYS_GETMSG(IER,,MESSAGE)
+	WRITE (6,'(A)') MESSAGE
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE HELP(LIBRARY)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) LIBRARY
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	IER = CLI$GET_VALUE('HELP_FOLDER',BULL_PARAMETER,LEN_P)
+	IF (.NOT.IER) BULL_PARAMETER = ' '
+
+	CALL OUTPUT_HELP(BULL_PARAMETER(1:LEN_P),LIBRARY)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE GET_NODE_INFO
+C
+C  SUBROUTINE GET_NODE_INFO
+C
+C  FUNCTION: Gets local node name and obtains node names from
+C	command line.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	EXTERNAL CLI$_ABSENT
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+
+	COMMON /TEMP_INPUT/ NODE_TEMP
+	CHARACTER NODE_TEMP*256
+
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+	CHARACTER LOCAL_NODE*32,PASSWORD*32,TEMP_USER*12
+
+	NODE_ERROR = .FALSE.
+
+	LOCAL_NODE_FOUND = .FALSE.
+	CALL LIB$SYS_TRNLOG('SYS$NODE',L_NODE,LOCAL_NODE)
+	L_NODE = L_NODE - 2			! Remove '::'
+	IF (LOCAL_NODE(1:1).EQ.'_') THEN
+	   LOCAL_NODE = LOCAL_NODE(2:)
+	   L_NODE = L_NODE - 1
+	END IF
+
+	NODE_NUM = 0				! Initialize number of nodes
+	IF (CLI$PRESENT('NODES')) THEN		! Decnet nodes specified?
+	   DO WHILE (CLI$GET_VALUE('NODES',NODE_TEMP)
+     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified nodes
+	    IER = SYS_TRNLNM(NODE_TEMP,NODE_TEMP)
+	    DO WHILE (TRIM(NODE_TEMP).GT.0)
+	      NODE_NUM = NODE_NUM + 1
+	      COMMA = INDEX(NODE_TEMP,',')
+	      IF (COMMA.GT.0) THEN
+		 NODES(NODE_NUM) = NODE_TEMP(1:COMMA-1)
+		 NODE_TEMP = NODE_TEMP(COMMA+1:)
+	      ELSE
+		 NODES(NODE_NUM) = NODE_TEMP
+		 NODE_TEMP = ' '
+	      END IF
+	      NLEN = TRIM(NODES(NODE_NUM))
+	      I = INDEX(NODES(NODE_NUM),'::')
+	      TEMP_USER = ' '
+	      IF (I.GT.0.AND.NLEN-I.EQ.1) THEN
+		 NLEN = NLEN - 2
+		 NODES(NODE_NUM) = NODES(NODE_NUM)(:NLEN)
+	      ELSE IF (I.GT.0.AND.NLEN-I.GT.1) THEN
+		 TEMP_USER = NODES(NODE_NUM)(I+2:)
+		 NLEN = I - 1
+		 NODES(NODE_NUM) = NODES(NODE_NUM)(:NLEN)
+	         POINT_NODE = NODE_NUM
+	         IER = 1
+	         DO WHILE (IER.NE.0)
+	            WRITE(6,'('' Enter password for node '',2A)')
+     &			NODES(NODE_NUM)(:NLEN),CHAR(10)
+		    CALL GET_INPUT_NOECHO(PASSWORD)
+		    IF (TRIM(PASSWORD).EQ.0) THEN
+		       DO WHILE (NODE_NUM.GT.0)
+		          CLOSE(UNIT=9+NODE_NUM)
+		          NODE_NUM = NODE_NUM - 1
+		       END DO
+		       NODE_ERROR = .TRUE.
+		       RETURN
+	            END IF
+	            OPEN (UNIT=9+NODE_NUM,NAME=NODES(NODE_NUM)(:NLEN)//
+     &		     '"'//TEMP_USER(:TRIM(TEMP_USER))//' '//
+     &		     PASSWORD(:TRIM(PASSWORD))//'"::'//'"TASK=BULLETIN"',
+     &		     ACCESS='SEQUENTIAL',FORM='FORMATTED',
+     &		     CARRIAGECONTROL='NONE',TYPE='NEW',IOSTAT=IER)
+		    IF (IER.NE.0) THEN
+		       WRITE (6,'('' ERROR: Password is invalid.'')')
+		    END IF
+	         END DO
+	      END IF
+	      IF (LOCAL_NODE(:L_NODE).EQ.NODES(NODE_NUM)(:NLEN)) THEN
+	         NODE_NUM = NODE_NUM - 1
+	         LOCAL_NODE_FOUND = .TRUE.
+	      ELSE IF (TRIM(TEMP_USER).EQ.0) THEN
+	         POINT_NODE = NODE_NUM
+	         OPEN (UNIT=9+NODE_NUM,NAME=NODES(NODE_NUM)(:NLEN)//
+     &		  '::"TASK=BULLETIN"',ACCESS='SEQUENTIAL',FORM='FORMATTED',
+     &		  CARRIAGECONTROL='NONE',TYPE='NEW',IOSTAT=IER)
+	         IF (IER.NE.0) THEN
+		    DO WHILE (NODE_NUM.GT.0)
+		       CLOSE(UNIT=9+NODE_NUM)
+		       NODE_NUM = NODE_NUM - 1
+		    END DO
+		    NODE_ERROR = .TRUE.
+		    RETURN
+	         END IF
+	      END IF
+	    END DO
+	   END DO
+	ELSE
+	   LOCAL_NODE_FOUND = .TRUE.
+	END IF
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_FOLDER_FILE(NUM)
+C
+C  SUBROUTINE SET_FOLDER_FILE
+C
+C  FUNCTION: Sets folder file name.  If NUM = 0, set FOLDER_FILE,
+C		if = 1, set FOLDER1_FILE
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	IF (NUM.EQ.0) THEN
+	   CALL SET_FILE(FOLDER,FOLDER_FLAG,FOLDER_NUMBER,FOLDER_FILE)
+	ELSE IF (NUM.EQ.1) THEN
+	   CALL SET_FILE(FOLDER1,FOLDER1_FLAG,FOLDER1_NUMBER,FOLDER1_FILE)
+	END IF
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SET_FILE(FOLDER,FOLDER_FLAG,FOLDER_NUMBER,FOLDER_FILE)
+C
+C  SUBROUTINE SET_FILE
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	CHARACTER*(*) FOLDER,FOLDER_FILE
+
+	IF (.NOT.BTEST(FOLDER_FLAG,8)) THEN
+	   FOLDER_FILE =
+     &		FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//FOLDER
+	ELSE
+	   FOLDER_FILE = NEWS_DIRECTORY(:TRIM(NEWS_DIRECTORY)-1)//
+     &		'.]'
+	END IF
+
+	RETURN
+	END
+
+
+
+
+        SUBROUTINE SET_BULLFIL
+
+        IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+        COMMON /BULLFIL/ BULLFIL
+
+	CHARACTER FILDATE*12
+
+	DATA UPDATE/.FALSE./, JUST_NAME/.FALSE./
+
+	UPDATE = .TRUE.
+	JUST_NAME = .TRUE.
+
+	ENTRY SET_BULLFIL_UPDATE
+
+	UPDATE = .NOT.UPDATE
+	JUST_NAME = .TRUE.
+
+	ENTRY SET_BULLFIL_NAME
+
+	JUST_NAME = .NOT.JUST_NAME
+
+	IER = SYS$ASCTIM(,FILDATE,EX_BTIM,) 
+	IF (.NOT.IER.OR.FILDATE.EQ.'17-NOV-1858 ') 
+     &				IER = SYS$ASCTIM(,FILDATE,,)
+	IF (BULLFIL.EQ.1) FILDATE = EXDATE
+	FILDATE = FILDATE(FIRST_ALPHA(FILDATE):)
+
+	M = INDEX(FILDATE,'-')
+	FOLDER1_FILE = FOLDER_FILE(:MINGT0(INDEX(FOLDER_FILE,'.]'),
+     &		INDEX(FOLDER_FILE,'.BULLNEWS')))//'BULLNEWS'//
+     &		FILDATE(INDEX(FILDATE,' ')-2:TRIM(FILDATE))//']'//
+     &		FILDATE(:M-1)//FILDATE(M+1:M+3)
+	
+	IF (FOLDER1_FILE.NE.FOLDER_FILE) THEN 
+	   FOLDER_FILE = FOLDER1_FILE
+	   IF (JUST_NAME) THEN
+	      JUST_NAME = .FALSE.
+	      RETURN
+	   END IF
+	   IF (BULLFIL.GT.0) CALL CLOSE_BULLFIL
+	   IF (BULLFIL.EQ.-1) THEN
+	      BULLFIL = 1
+	      CALL OPEN_BULLFIL
+	   ELSE IF (BULLFIL.EQ.-2) THEN
+	      BULLFIL = 2
+	      CALL OPEN_BULLFIL_SHARED
+	   END IF
+	END IF
+
+	JUST_NAME = .FALSE.
+	
+        IF (UPDATE) THEN	
+	   READ (1'1) NBLOCK
+	   REWRITE (1) NBLOCK + LENGTH
+	   UPDATE = .FALSE.
+	END IF
+
+	RETURN
+	END
+
+
+
+	INTEGER FUNCTION MINGT0(I,J)
+
+        IMPLICIT INTEGER (A-Z)
+
+	IF (I.LE.0) THEN
+	   MINGT0 = J
+	ELSE IF (J.LE.0) THEN
+	   MINGT0 = I
+	ELSE
+	   MINGT0 = MIN(I,J)
+	END IF	
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bulletin9.for b/decus/vmslt98a/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..e068c2e2885c317ffd0f115dfd82c9bd2c17ab67
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulletin9.for
@@ -0,0 +1,2477 @@
+C
+C  BULLETIN9.FOR, Version 4/8/98
+C  Purpose: Contains subroutines for the bulletin board utility program.
+C  Environment: VAX/VMS
+C  Usage: Invoked by the BULLETIN command.
+C  Programmer: Mark R. London
+C
+C  Copyright (c) 1990
+C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
+C  This program cannot be copied or distributed in any form for non-MIT
+C  use without specific written approval of MIT Plasma Fusion Center
+C  Management.
+C
+	SUBROUTINE DELETE_NODE
+C
+C  SUBROUTINE DELETE_NODE
+C
+C  FUNCTION: Deletes files sent via ADD/NODES at remote hosts.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
+     &				NODE_ERROR,POINT_NODE
+	CHARACTER*32 NODES(10)
+	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR
+
+    	CHARACTER INLINE*80
+
+	CALL GET_NODE_INFO
+
+ 	IF (NODE_ERROR) GO TO 940
+
+	IF (NODE_NUM.EQ.0.OR.LOCAL_NODE_FOUND) THEN
+	   WRITE (6,'('' ERROR: Cannot specify local node.'')')
+	   GO TO 999
+	END IF
+
+	IER = CLI$GET_VALUE('SUBJECT',DESCRIP)
+
+	DO POINT_NODE=1,NODE_NUM	   	! Write out command to nodes
+	   NLEN = TRIM(NODES(POINT_NODE))	! Length of node name
+	   INLINE = 'DELETE/SUBJECT="'//DESCRIP(:TRIM(DESCRIP))
+	   WRITE (POINT_NODE+9,'(A)',ERR=940) INLINE
+	   READ (POINT_NODE+9,'(A)',ERR=940,END=940) INLINE
+	   IF (INLINE.EQ.'END') THEN
+	      WRITE (6,'('' Message successfully deleted from node '',A)')
+     &				NODES(POINT_NODE)
+	   ELSE
+	      WRITE (6,'('' Error while deleting message to node '',A)')
+     &				NODES(POINT_NODE)
+	      WRITE (6,'(A)') INLINE
+	   END IF
+	END DO
+
+	GO TO 999
+
+940	WRITE (6,1015) NODES(POINT_NODE)
+
+999	DO WHILE (NODE_NUM.GT.0)
+	   CLOSE(UNIT=9+NODE_NUM)
+	   NODE_NUM = NODE_NUM - 1
+	END DO
+
+	RETURN
+
+1015	FORMAT (' ERROR: Unable to reach node ',A)
+
+	END
+
+
+
+
+	SUBROUTINE SET_FOLDER_FLAG(SETTING,FLAG,FLAGNAME)
+C
+C  SUBROUTINE SET_FOLDER_FLAG
+C
+C  FUNCTION: Sets or clears specified flag for folder
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CHARACTER*(*) FLAGNAME
+
+	IF (REMOTE_SET.EQ.3.OR.(REMOTE_SET.EQ.4.AND.FLAG.NE.1)) THEN
+	   WRITE (6,'('' ERROR: Command invalid for folder.'')')
+	ELSE IF ((FLAG.EQ.7.OR.FLAG.EQ.14).AND..NOT.SETPRV_PRIV()) THEN
+	   WRITE (6,'('' ERROR: Privileges required for this command.'')')
+	ELSE IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+           IF (REMOTE_SET.NE.4) THEN
+	      CALL OPEN_BULLFOLDER		! Open folder file
+	   ELSE
+	      CALL OPEN_BULLNEWS_SHARED
+	   END IF
+
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	   IF (SETTING) THEN
+	      FOLDER_FLAG = IBSET(FOLDER_FLAG,FLAG)
+	   ELSE
+	      FOLDER_FLAG = IBCLR(FOLDER_FLAG,FLAG)
+	   END IF
+
+	   CALL REWRITE_FOLDER_FILE(IER)
+
+	   CALL CLOSE_BULLFOLDER
+
+	   WRITE (6,'(1X,A,'' has been modified for folder.'')')
+     &		FLAGNAME
+	ELSE
+	   WRITE (6,'(1X,'' You are not authorized to modify '',A)')
+     &		FLAGNAME//'.'
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_FOLDER_EXPIRE_LIMIT(LIMIT)
+C
+C  SUBROUTINE SET_FOLDER_EXPIRE_LIMIT
+C
+C  FUNCTION: Sets folder expiration limit.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLFILES.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	IF (REMOTE_SET.EQ.3) THEN
+	   WRITE (6,'('' ERROR: Command invalid for folder. '')')
+	ELSE IF (LIMIT.LT.0) THEN
+	   WRITE (6,'('' ERROR: Invalid expiration length specified.'')')
+	ELSE IF (FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
+           IF (REMOTE_SET.NE.4) THEN
+	      CALL OPEN_BULLFOLDER		! Open folder file
+	   ELSE
+	      CALL OPEN_BULLNEWS_SHARED
+	   END IF
+
+	   CALL READ_FOLDER_FILE_KEYNAME(FOLDER,IER)
+
+	   F_EXPIRE_LIMIT = LIMIT
+
+	   CALL REWRITE_FOLDER_FILE(IER)
+
+	   CALL CLOSE_BULLFOLDER
+	   WRITE (6,'('' Folder expiration date modified.'')')
+	ELSE
+	   WRITE (6,'('' You are not allowed to modify folder.'')')
+	END IF
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE MERGE
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(DIR_RECORD_LENGTH) BULLDIR_ENTRY_SAVE
+
+	ENTRY INITIALIZE_MERGE(IER1)
+
+	DO WHILE (FILE_LOCK(IER1,IER2))
+	   OPEN (UNIT=24,FILE=FOLDER_FILE(:TRIM(FOLDER_FILE))
+     &		//'.TMPDIR',STATUS='NEW',FORM='UNFORMATTED',
+     &		RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
+     &		ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
+     &		KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
+	END DO
+
+	IF (IER1.NE.0) RETURN
+
+	NBULL = 0
+
+	WRITE(24,IOSTAT=IER1) BULLDIR_HEADER
+	CALL CONVERT_HEADER_FROMBIN
+
+	TO_POINTER = 1
+
+	RETURN
+
+	ENTRY ADD_MERGE_TO(IER1)
+ 
+	IER1 = 0
+
+	DO WHILE (IER1.EQ.0)
+
+	   BULLDIR_ENTRY_SAVE = BULLDIR_ENTRY
+
+	   CALL READDIR(TO_POINTER,IER)
+
+	   DIFF = COMPARE_BTIM(%REF(BULLDIR_ENTRY_SAVE),MSG_BTIM)
+	   IF (DIFF.LT.0.OR.TO_POINTER+1.NE.IER) THEN
+	      BULLDIR_ENTRY = BULLDIR_ENTRY_SAVE
+	      CALL CONVERT_ENTRY_FROMBIN
+	      RETURN
+	   END IF
+
+	   NBULL = NBULL + 1
+	   MSG_NUM = NBULL
+
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   WRITE(24,IOSTAT=IER1) BULLDIR_ENTRY
+
+	   NEWEST_DATE = DATE
+	   NEWEST_TIME = TIME
+
+	   TO_POINTER = TO_POINTER + 1
+
+	   BULLDIR_ENTRY = BULLDIR_ENTRY_SAVE
+	END DO
+
+	CLOSE (UNIT=24)
+
+	RETURN
+
+	ENTRY ADD_MERGE_FROM(IER1)
+
+	NEWEST_DATE = DATE
+	NEWEST_TIME = TIME
+
+	DIFF = COMPARE_DATE(NEWEST_EXDATE,EXDATE)
+	IF (DIFF.GT.0) THEN
+	   NEWEST_EXDATE = EXDATE
+	   NEWEST_EXTIME = EXTIME
+	ELSE IF (DIFF.EQ.0) THEN
+	   DIFF = COMPARE_TIME(NEWEST_EXTIME,EXTIME)
+	   IF (DIFF.GT.0) NEWEST_EXTIME = EXTIME
+	END IF
+
+	IF ((SYSTEM.AND.4).EQ.4) THEN
+	   SHUTDOWN = SHUTDOWN + 1
+	   SHUTDOWN_DATE = DATE
+	   SHUTDOWN_TIME = TIME
+	END IF
+
+	BLOCK = NBLOCK - LENGTH
+
+	NBULL = NBULL + 1
+	MSG_NUM = NBULL
+
+	CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	WRITE(24,IOSTAT=IER1) BULLDIR_ENTRY
+
+	RETURN
+
+	ENTRY ADD_MERGE_REST(IER1)
+
+	CALL UPDATE_LOGIN(.TRUE.)
+
+	DO WHILE (IER1.EQ.0)
+
+	   CALL READDIR(TO_POINTER,IER)
+	   IF (TO_POINTER+1.NE.IER) THEN
+	      READ (24,KEYID=0,KEY=0,IOSTAT=IER1)
+	      CALL CONVERT_HEADER_TOBIN
+	      REWRITE(24,IOSTAT=IER1) BULLDIR_HEADER
+	      IF (IER1.EQ.0) THEN
+	         CLOSE (UNIT=24,DISPOSE='KEEP')
+	         CALL LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))//
+     &		  '.TMPDIR',FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLDIR')
+	      ELSE
+		 CLOSE (UNIT=24)
+	      END IF
+	      RETURN
+	   END IF
+
+	   NBULL = NBULL + 1
+	   MSG_NUM = NBULL
+
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+	   WRITE(24,IOSTAT=IER1) BULLDIR_ENTRY
+
+	   NEWEST_DATE = DATE
+	   NEWEST_TIME = TIME
+
+	   TO_POINTER = TO_POINTER + 1
+	END DO
+
+	CLOSE (UNIT=24)
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_NOKEYPAD
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+	INCLUDE '($SMGDEF)'
+
+	KEYPAD_MODE = 0
+
+	TERM = SMG$M_KEY_TERMINATE
+
+	IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,0)
+
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF2',,TERM,'SET KEYPAD',)
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE SET_KEYPAD
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+	COMMON /KEYPAD/ KEYPAD_MODE
+
+        COMMON /KEYLOAD/ LOAD_KEY
+
+	INCLUDE '($SMGDEF)'
+
+	KEYPAD_MODE = 1
+
+	TERM = SMG$M_KEY_TERMINATE
+
+	IER = SMG$SET_KEYPAD_MODE(KEYBOARD_ID,1)
+
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF1',,,,'GOLD')
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF2',,TERM,'HELP',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF2','GOLD',TERM,'SET NOKEYPAD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF3',,,'EXTRACT ',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF3','GOLD',,'FILE ',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF4',,TERM,'SHOW KEYPAD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PF4','GOLD',TERM,
+     &		'SHOW KEYPAD/PRINT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP0',,TERM,
+     &		'SHOW FOLDER/FULL',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP0','GOLD',TERM,'SHOW FLAGS',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP1',,TERM,'BACK',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP1','GOLD',TERM,'NEXT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP2',,TERM,'PRINT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP2','GOLD',TERM,'PRINT/NONOTIFY',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP3',,TERM,'DIR',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP3','GOLD',TERM,'DIR/FOLDER',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP4',,TERM,'CURRENT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP4','GOLD',TERM,'CURRENT/EDIT ',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP5',,TERM,'RESPOND',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP5','GOLD',TERM,'RESP/EDIT/EXT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP6',,TERM,'LAST',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP7',,TERM,'ADD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP7','GOLD',TERM,'ADD/EDIT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP8',,TERM,'REPLY',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP8','GOLD',TERM,'REPL/EDIT/EXT',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP9',,TERM,'MAIL',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'KP9','GOLD',TERM,'MAIL/NOHEAD',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'MINUS',,TERM,'READ/NEW',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'MINUS','GOLD',TERM,'SHOW NEW',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'COMMA',,TERM,'DIR/NEW',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'COMMA','GOLD',TERM,'INDEX',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PERIOD',,TERM,'DELETE',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'PERIOD','GOLD',TERM,'UNDELETE',)
+	IER = SMG$ADD_KEY_DEF(KEY_TABLE_ID,'ENTER','GOLD',,'SELECT ',)
+
+        LOAD_KEY = SMG$LOAD_KEY_DEFS(KEY_TABLE_ID,'BULL_INIT',
+     &				'SYS$LOGIN:BULL.INI',1)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE SHOW_KEYPAD(LIBRARY)
+
+	IMPLICIT INTEGER (A-Z)
+	EXTERNAL LIB$PUT_OUTPUT,PRINT_OUTPUT
+	CHARACTER*(*) LIBRARY
+
+	COMMON /SMG/ KEYBOARD_ID,KEY_TABLE_ID
+
+        COMMON /KEYLOAD/ LOAD_KEY
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	INCLUDE '($HLPDEF)'
+
+	CHARACTER KEY*10,EQU*50,ST*20,IFS*20
+
+	OUT = 6
+
+	IF (CLI$PRESENT('PRINT')) THEN
+	   OPEN (UNIT=8,STATUS='NEW',FILE='SYS$LOGIN:KEYPAD.DAT',
+     &			IOSTAT=IER)
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR WHILE OPENING FILE TO PRINTER.'')')
+	      RETURN
+	   END IF
+	   OUT = 8
+	END IF      
+
+	IF (CLI$GET_VALUE('SHOW_KEY',KEY,I)) THEN
+	   DO WHILE (CLI$GET_VALUE('STATE',IFS,J))
+              IER = SMG$GET_KEY_DEF(
+     &			KEY_TABLE_ID,KEY(:I),IFS(:J),ATT,EQU,ST)
+              WRITE (OUT,'(3X,A,$)') KEY(:TRIM(KEY))//' = '//'"'//
+     &                                  EQU(:TRIM(EQU))//'"'
+	      IF (TRIM(ST).GT.0) THEN
+	         WRITE (OUT,'(A,$)') '+ '//'state='//ST(:TRIM(ST))
+	      END IF
+              IF (TRIM(IFS).GT.0.AND.IFS.NE.'DEFAULT') THEN
+                 WRITE (OUT,'(A,$)') '+ '//'ifstate='//IFS(:TRIM(IFS))
+              END IF
+	      WRITE (OUT,'(A)') '+'
+	   END DO
+	   RETURN
+ 	ELSE IF (LOAD_KEY) THEN
+	   C = 0
+	   IER = 1
+	   WRITE (OUT,'(1X,A)') 'Keypad definitions:'
+	   L = 1
+	   DO WHILE (IER)
+	      IER = SMG$LIST_KEY_DEFS(KEY_TABLE_ID,C,KEY,IFS,ATT,EQU,ST)
+	      IF (IER) THEN
+		 WRITE (OUT,'(3X,A,$)') KEY(:TRIM(KEY))//' = '//'"'//
+     &					EQU(:TRIM(EQU))//'"'
+	         IF (TRIM(ST).GT.0) THEN
+		    WRITE (OUT,'(A,$)') '+ '//'state='//ST(:TRIM(ST))
+		 END IF
+                 IF (TRIM(IFS).GT.0.AND.IFS.NE.'DEFAULT') THEN
+                    WRITE (OUT,'(A,$)') '+ '//'ifstate='
+     &						//IFS(:TRIM(IFS))
+                 END IF
+		 WRITE (OUT,'(A)') '+'
+ 		 L = L + 1
+                 IF (PAGING.AND.L.EQ.PAGE_LENGTH-1.AND.OUT.EQ.6) THEN
+                    L = 0                        ! Reinitialize screen counter
+	            CALL LIB$PUT_OUTPUT(' ')
+		    CALL GET_INPUT_NOECHO_PROMPT(
+     &				KEY(:1),'Press key to continue ... ')
+             	    IER = LIB$ERASE_PAGE(1,1)         ! Erase display
+		 END IF
+	      END IF
+	   END DO
+           IF (OUT.EQ.8) CLOSE (UNIT=8,DISP='PRINT/DELETE')
+	   RETURN
+	END IF
+
+	IF (OUT.EQ.8) THEN
+	   CALL LBR$OUTPUT_HELP(PRINT_OUTPUT,,'KEYPAD'
+     &		,LIBRARY,HLP$M_HELP)
+	   CLOSE (UNIT=8,DISP='PRINT/DELETE')
+	ELSE
+	   CALL LBR$OUTPUT_HELP(LIB$PUT_OUTPUT,,'KEYPAD'
+     &		,LIBRARY,HLP$M_HELP)
+	END IF
+
+	RETURN
+	END
+
+	INTEGER FUNCTION PRINT_OUTPUT(INPUT)
+	IMPLICIT INTEGER (A-Z)
+	CHARACTER*(*) INPUT
+	WRITE (8,'(1X,A)',IOSTAT=IER) INPUT(:TRIM(INPUT))
+	IF (IER.EQ.0) PRINT_OUTPUT = 1
+	RETURN
+	END
+
+
+
+	SUBROUTINE OUTPUT_HELP(PARAMETER,LIBRARY)
+C
+C  SUBROUTINE OUTPUT_HELP
+C
+C  FUNCTION:
+C	To create interactive help session.  Prompting is enabled.
+C  INPUTS:
+C	PARAMETER - Character string. Optional input parameter
+C		    containing a list of help keys.
+C	LIBRARY   - Character string. Name of help library.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($LBRDEF)'
+
+	COMMON /HELP/ HELP_PAGE,HELP_INPUT,HELP_INPUT_LEN
+	COMMON /HELP/ NEED_ERASE,KEYBOARD_ID,KEY_TABLE_ID,OTHERINFO
+	CHARACTER*80 HELP_INPUT
+
+	COMMON /LEVELS/ KEY,KEYL,NKEY,OLD_NKEY,EXACT
+	CHARACTER*20 KEY(10)
+	DIMENSION KEYL(10)
+
+	EXTERNAL PUT_OUTPUT
+
+	CHARACTER*(*) LIBRARY,PARAMETER
+
+	CHARACTER*80 PROMPT
+
+	DATA KEYBOARD_ID/0/
+
+	IF (KEYBOARD_ID.EQ.0) THEN
+	   IER = SMG$CREATE_VIRTUAL_KEYBOARD(KEYBOARD_ID,,,,20)
+	   IER = SMG$CREATE_KEY_TABLE(KEY_TABLE_ID)
+	END IF
+
+	CALL STR$TRIM(HELP_INPUT,PARAMETER,HELP_INPUT_LEN)	! Trim input
+
+	CALL LBR$INI_CONTROL(LINDEX,LBR$C_READ)		! Init library read
+	CALL LBR$OPEN(LINDEX,LIBRARY)			! Specify library name
+
+	DO I=1,10					! Initialize key lengths
+	   KEYL(I) = 0
+	END DO
+
+	NKEY = 0					! Number of help keys
+
+	DO WHILE (NKEY.GE.0)	! Do until CTRL-Z entered or no more keys
+
+	   HELP_PAGE = 0				! Init line counter
+	   NEED_ERASE = .TRUE.				! Need to erase screen
+
+	   OLD_NKEY = NKEY				! Save old key count
+	   EXACT = .TRUE.				! Exact key match
+
+	   DO WHILE (NKEY.LT.10.AND.HELP_INPUT_LEN.GT.0.AND.
+     &					   HELP_INPUT(:1).NE.'?')
+							! Break input into keys
+	      NKEY = NKEY + 1				! Increment key counter
+
+	      DO WHILE (HELP_INPUT(1:1).EQ.' '.AND.HELP_INPUT_LEN.GT.0)
+		 HELP_INPUT = HELP_INPUT(2:HELP_INPUT_LEN)	! Strip spaces
+		 HELP_INPUT_LEN = HELP_INPUT_LEN - 1	! at start of input
+	      END DO
+
+	      NEXT_KEY = 2
+
+	      DO WHILE (NEXT_KEY.LE.HELP_INPUT_LEN		! Search for
+     &		  .AND.HELP_INPUT(NEXT_KEY:NEXT_KEY).NE.' '	! space or
+     &		  .AND.HELP_INPUT(NEXT_KEY:NEXT_KEY).NE.'/')	! backslash
+		 NEXT_KEY = NEXT_KEY + 1	! indicating start of next key
+	      END DO
+
+	      IF (NEXT_KEY.GT.HELP_INPUT_LEN) THEN	! Found the last key
+		 KEY(NKEY) = HELP_INPUT(:HELP_INPUT_LEN)	! Key string
+		 KEYL(NKEY) = HELP_INPUT_LEN			! Key length
+		 HELP_INPUT_LEN = 0
+	      ELSE					! Found the next key
+		 KEY(NKEY) = HELP_INPUT(:NEXT_KEY-1)
+		 HELP_INPUT = HELP_INPUT(NEXT_KEY:HELP_INPUT_LEN)
+		 KEYL(NKEY) = NEXT_KEY - 1
+		 HELP_INPUT_LEN = HELP_INPUT_LEN - NEXT_KEY + 1
+	      END IF
+	   END DO
+	   HELP_INPUT_LEN = 0
+	   IER = LBR$GET_HELP(LINDEX,,PUT_OUTPUT,,	! Display help
+     &		   KEY(1)(:KEYL(1)),KEY(2)(:KEYL(2)),
+     &		   KEY(3)(:KEYL(3)),KEY(4)(:KEYL(4)),KEY(5)(:KEYL(5)),
+     &		   KEY(6)(:KEYL(6)),KEY(7)(:KEYL(7)),KEY(8)(:KEYL(8)),
+     &		   KEY(9)(:KEYL(9)),KEY(10)(:KEYL(10)))
+
+	   IF (IER.EQ.0.AND.HELP_INPUT_LEN.GT.0) IER = 1
+		! IER = 0 special case means input given to full screen prompt
+
+	   IF (KEY(NKEY).EQ.'*'.OR..NOT.EXACT) THEN	! If not exact match
+	      DO I=OLD_NKEY+1,NKEY			! then don't update
+		 KEYL(I) = 0				! new keys
+	      END DO
+	      NKEY = OLD_NKEY
+	   END IF
+
+	   IF (IER.AND.NKEY.GT.0.AND.OTHERINFO.EQ.0) THEN ! No subtopics?
+	      KEYL(NKEY) = 0				! Back up one key level
+	      NKEY = NKEY - 1
+	   END IF
+
+	   DO WHILE (HELP_INPUT_LEN.EQ.0.AND.IER.AND.NKEY.GE.0)
+	      IF (NKEY.EQ.0) THEN	! If top level, prompt for topic
+	         IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		   HELP_INPUT,'Topic? ',HELP_INPUT_LEN)
+	      ELSE			! If not top level, prompt for subtopic
+		 LPROMPT = 0		! Create subtopic prompt line
+		 DO I=1,NKEY		! Put spaces in between keys
+		    PROMPT = PROMPT(:LPROMPT)//KEY(I)(:KEYL(I))//' '
+		    LPROMPT = LPROMPT + KEYL(I) + 1
+		 END DO
+		 PROMPT = PROMPT(:LPROMPT)//'Subtopic? '
+		 LPROMPT = LPROMPT + 10
+	         IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		   HELP_INPUT,PROMPT(:LPROMPT),HELP_INPUT_LEN)
+	      END IF
+	      CALL STR$TRIM(HELP_INPUT,HELP_INPUT,HELP_INPUT_LEN)
+	      IF (IER.AND.HELP_INPUT_LEN.EQ.0) THEN	! If RETURN entered
+		 KEYL(NKEY) = 0				! Back up one key level
+		 NKEY = NKEY - 1
+	      END IF
+	   END DO
+
+	   IF (.NOT.IER.OR.NKEY.LT.0) THEN	! If CTRL-Z above top level,
+	      CALL LIB$PUT_OUTPUT(' ')		! Skip line
+	      CALL LBR$CLOSE(LINDEX)		! then close library,
+	      RETURN				! and end help session.
+	   END IF
+
+	END DO
+
+	END
+
+
+
+	INTEGER FUNCTION PUT_OUTPUT(INPUT,INFO,DATA,LEVEL)
+C
+C  FUNCTION PUT_OUTPUT
+C
+C  FUNCTION:
+C	Output routine for input from LBR$GET_HELP.  Displays
+C	help text on terminal with full screen prompting.
+C  INPUTS:
+C	INPUT - Character string.  Line of input text.
+C	INFO  - Longword.  Contains help flag bits.
+C	DATA  - Longword.  Not presently used.
+C	LEVEL - Longword.  Contains current key level.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE '($HLPDEF)'
+
+	COMMON /LEVELS/ KEY,KEYL,NKEY,OLD_NKEY,EXACT
+	CHARACTER*20 KEY(10)
+	DIMENSION KEYL(10)
+
+	COMMON /HELP/ HELP_PAGE,HELP_INPUT,HELP_INPUT_LEN
+	COMMON /HELP/ NEED_ERASE,KEYBOARD_ID,KEY_TABLE_ID,OTHERINFO
+	CHARACTER*80 HELP_INPUT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+
+	CHARACTER INPUT*(*)
+
+	CHARACTER SPACES*20
+	DATA SPACES /' '/
+
+	OTHERINFO = INFO.AND.HLP$M_OTHERINFO
+
+	IF ((INFO.AND.HLP$M_NOHLPTXT).NE.0) THEN	! Key cannot be found
+	   NEED_ERASE = .FALSE.				! Don't erase screen
+	   IF (HELP_PAGE.EQ.0) THEN		! If first line of help text
+	      DO I=OLD_NKEY+1,NKEY		! remove any new keys that
+		 KEYL(I) = 0			! were inputted, as they are
+	      END DO				! not valid, as no match
+	      NKEY = OLD_NKEY			! could be found.
+	   END IF
+	ELSE IF ((INFO.AND.HLP$M_KEYNAMLIN).NE.0.AND.NKEY.GT.0.AND.
+     &		 LEVEL.GT.OLD_NKEY.AND.KEY(NKEY)(:KEYL(NKEY)).NE.'*'.AND.
+     &		 %LOC(INPUT).NE.0) THEN		! If text contains key names
+			! Update if not wildcard search and they are new keys
+	   IF (KEYL(LEVEL).GT.0) THEN		! If key already updated
+	      EXACT = .FALSE.		! Must be more than one match possible
+	   END IF			! so indicate not exact match.
+	   START_KEY = 1		! String preceeding spaces.
+	   DO WHILE (INPUT(START_KEY:START_KEY).EQ.' ')
+	      START_KEY = START_KEY + 1
+	   END DO
+	   KEY(LEVEL) = INPUT(START_KEY:)			! Store new key
+	   CALL STR$TRIM(KEY(LEVEL),KEY(LEVEL),KEYL(LEVEL))	! & key length
+	ELSE IF (HELP_PAGE.EQ.0) THEN		! If first line of text,
+	   DO I=OLD_NKEY+1,NKEY			! remove any new keys that
+	      KEYL(I) = 0			! were just inputted, allowing
+	   END DO				! this routine to fill them.
+	END IF
+
+	IF (NEED_ERASE) THEN			! Need to erase screen?
+	   IER = LIB$ERASE_PAGE(1,1)		! i.e. start of new topic.
+	   NEED_ERASE = .FALSE.
+	END IF
+
+	HELP_PAGE = HELP_PAGE + 1		! Increment screen counter
+	IF (PAGING.AND.HELP_PAGE.GT.PAGE_LENGTH-2) THEN		! End of page?
+	   HELP_PAGE = 0			! Reinitialize screen counter
+	   CALL LIB$PUT_OUTPUT(' ')	! Skip line and prompt for next screen
+	   IER = SMG$READ_COMPOSED_LINE(KEYBOARD_ID,KEY_TABLE_ID,
+     &		HELP_INPUT,'Press RETURN to continue ... ',HELP_INPUT_LEN)
+	   CALL STR$TRIM(HELP_INPUT,HELP_INPUT,HELP_INPUT_LEN)	! Trim input
+	   IF (.NOT.IER.OR.HELP_INPUT_LEN.GT.0) THEN	! CTRL-Z or Text input?
+	      EXACT = .TRUE.	! If more than one match was found and being
+				! displayed, text input specifies that the
+				! current displayed match is desired.
+	      PUT_OUTPUT = 0	! Stop any more of current help display.
+	   ELSE					! Else if RETURN entered
+	      IER = LIB$ERASE_PAGE(1,1)		! Erase display
+	      NSPACES = LEVEL*2		! Number of spaces to indent output
+	      IF ((INFO.AND.HLP$M_KEYNAMLIN).NE.0) NSPACES = NSPACES - 2
+		! Key name lines are indented 2 less than help description.
+	      IF (NSPACES.GT.0) THEN	! Add spaces if present to output
+		 PUT_OUTPUT =  LIB$PUT_OUTPUT(SPACES(:NSPACES)//INPUT)
+	      ELSE			! Else just output text.
+		 PUT_OUTPUT =  LIB$PUT_OUTPUT(INPUT)
+	      END IF
+	      HELP_PAGE = 1		! Increment page counter.
+	   END IF
+	ELSE				! Else if not end of page
+	   NSPACES = LEVEL*2		! Just output text line
+	   IF ((INFO.AND.HLP$M_KEYNAMLIN).NE.0) NSPACES = NSPACES - 2
+	   IF (NSPACES.GT.0) THEN
+	      PUT_OUTPUT = LIB$PUT_OUTPUT(SPACES(:NSPACES)//INPUT)
+	   ELSE
+	      PUT_OUTPUT = LIB$PUT_OUTPUT(INPUT)
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SHOW_VERSION
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLUSER.INC'
+
+	CHARACTER VERSION*12,DATE*24
+
+	INTEGER BTIM(2)
+
+	CALL READ_HEADER(VERSION,DATE)
+
+	WRITE (6,'(A)') ' BULLETIN Version '//VERSION(:TRIM(VERSION))
+
+	WRITE (6,'(A)') ' Linked on '//DATE(:TRIM(DATE))
+
+	RETURN
+
+	ENTRY SHOW_NEW_VERSION
+
+	CALL READ_HEADER(VERSION,DATE)
+
+	IER = SYS$BINTIM(DATE(:TRIM(DATE)),BTIM)
+	IF (.NOT.IER) RETURN
+
+C	IF (COMPARE_BTIM(READ_BTIM,BTIM).LT.0) THEN
+C	   WRITE (6,'(A)') ' A new BULLETIN executable has been '//
+C     &			   'installed since your last use.'
+C	   WRITE (6,'(A)') 
+C     &		' Type HELP NEW_FEATURES for help on any new features.'
+C	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FULL_DIR
+C
+C	Add INDEX command to BULLETIN, display directories of ALL
+C	folders.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+	INCLUDE 'BULLFILES.INC'
+	INCLUDE 'BULLFOLDER.INC'
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /TAGS/ BULL_TAG,READ_TAG
+
+        COMMON /NEW_DIR/ NEW
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
+	LOGICAL PAGING
+
+	DATA FOLDER_Q1/0/
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /COUNT/
+     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
+     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
+     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
+     &	   INDEX_COUNT
+
+	CHARACTER NEWS_ACCESS*132,DATETIME*20
+
+	EXTERNAL BULLETIN_SUBCOMMANDS
+
+	BULL_POINT = 0
+
+	IF (NUM_FOLDERS.GT.0.AND..NOT.CLI$PRESENT('RESTART')
+     &		.AND.INDEX_COUNT.EQ.1) THEN
+	   INDEX_COUNT = 2
+	   DIR_COUNT = 0
+	END IF
+
+	IF (INDEX_COUNT.EQ.1) THEN
+	  CALL INIT_QUEUE(FOLDER_Q1,FOLDER1_COM)
+
+	  FOLDER_Q = FOLDER_Q1
+
+	  SET = CLI$PRESENT('SET')
+	  NEW = CLI$PRESENT('NEW')
+	  INEW = NEW
+
+	  IREAD_TAG = IBSET(0,1) + IBSET(0,2)
+	  IF (CLI$PRESENT('MARKED')) THEN
+	     IREAD_TAG = 1 + IBSET(0,1)
+	  ELSE IF (CLI$PRESENT('SEEN')) THEN
+	     IREAD_TAG = 1 + IBSET(0,2)
+	  ELSE IF (CLI$PRESENT('UNMARKED').OR.CLI$PRESENT
+     &		   ('MARKED').EQ.%LOC(CLI$_NEGATED)) THEN
+	     IREAD_TAG = 1 + IBSET(0,1) + IBSET(0,3)
+	  ELSE IF (CLI$PRESENT('UNSEEN').OR.CLI$PRESENT
+     &		   ('SEEN').EQ.%LOC(CLI$_NEGATED)) THEN
+	     IREAD_TAG = 1 + IBSET(0,2) + IBSET(0,3)
+ 	  END IF
+
+	  NEW = NEW.AND..NOT.IREAD_TAG
+
+	  SUBSCRIBE = CLI$PRESENT('SUBSCRIBE')
+	  IF (SUBSCRIBE) THEN
+	     CALL NEWS_GET_SUBSCRIBE(0,F1_COUNT)
+	     SUBNUM = 1
+	     CALL OPEN_BULLNEWS_SHARED
+	  ELSE
+	     CALL OPEN_BULLFOLDER_SHARED
+	  END IF
+
+	  NUM_FOLDERS = 0
+	  IER = 0
+	  DO WHILE (IER.EQ.0)			! Copy all bulletins from file
+	    IF (SUBSCRIBE) THEN
+	       IER = 1
+	       DO WHILE (SUBNUM.NE.0.AND.IER.NE.0)
+	          CALL NEWS_GET_SUBSCRIBE(SUBNUM,MSGNUM)
+		  IF (SUBNUM.NE.0) THEN
+	             CALL READ_FOLDER_FILE_KEYNUM_TEMP(SUBNUM,IER)
+		     IF (IER.NE.0) THEN
+			SUBNUM = -1
+		     ELSE IF (NEW.AND.(MSGNUM.GE.F1_NBULL.OR.F1_NBULL
+     &			  .EQ.0.OR.F1_START.GT.F1_NBULL)) THEN
+		        IER = 1
+	             END IF
+		  END IF
+	       END DO
+	       IF (SUBNUM.EQ.0) IER = 1
+	    ELSE
+	       FOUND = .FALSE.
+	       DO WHILE (.NOT.FOUND.AND.IER.EQ.0)
+	          CALL READ_FOLDER_FILE_TEMP(IER)
+	          IF (IER.EQ.0) THEN
+		     IF (.NOT.SET.OR.TEST2(SET_FLAG,FOLDER1_NUMBER)
+     &			.OR.TEST2(BRIEF_FLAG,FOLDER1_NUMBER)) THEN
+			FOUND = .NOT.NEW.OR.COMPARE_BTIM(LAST_READ_BTIM
+     &			   (1,FOLDER1_NUMBER+1),F1_NEWEST_BTIM).LT.0
+                     END IF
+	          END IF
+	       END DO
+	    END IF
+	    IF (IER.EQ.0) THEN
+	      IF (BTEST(FOLDER1_FLAG,0).AND..NOT.SETPRV_PRIV()) THEN
+		 FOLDER1_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
+     &					//FOLDER1
+	         IF (SUBSCRIBE) THEN
+	            CALL CHECK_ACCESS
+     &		     (NEWS_ACCESS(FOLDER_DESCRIP),
+     &		      USERNAME,READ_ACCESS,-1)
+	         ELSE
+	            CALL CHECK_ACCESS
+     &		     (FOLDER1_FILE(:TRIM(FOLDER1_FILE))//'.BULLFIL',
+     &		      USERNAME,READ_ACCESS,-1)
+	         END IF
+	      ELSE
+		 READ_ACCESS = 1
+	      END IF
+	      IF (READ_ACCESS) THEN
+	         NUM_FOLDERS = NUM_FOLDERS + 1
+	         CALL WRITE_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER1_COM)
+	      END IF
+	    END IF
+	  END DO
+
+	  CALL CLOSE_BULLFOLDER			! We don't need file anymore
+
+	  FOLDER_Q = FOLDER_Q1			! Init queue pointer to header
+	  IF (NEW) THEN
+	     WRITE (6,1010)
+	  ELSE
+	     WRITE (6,1000)
+	  END IF
+	  IF (.NOT.SUBSCRIBE) THEN
+	     WRITE (6,'(1X,''Folder'',22X,''Last message'',7X,''Messages'',
+     &		2X,''Owner'',/,1X,80(''-''))')
+	  ELSE
+	     WRITE (6,'(1X,''News group'',<PAGE_WIDTH-80+39>X,1X,
+     &		''First        Last   Last Read'',/,1X,<PAGE_WIDTH>(''-''))')
+	  END IF
+          NUM_FOLDER = 0
+	  IF (SUBSCRIBE) FLEN = MIN(81,PAGE_WIDTH-80+42)
+	  DO I = 1,NUM_FOLDERS
+	   CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER1_COM)
+	   IF (SUBSCRIBE) THEN
+	      J = INDEX(FOLDER1_DESCRIP,' ')
+	      IF (J.GT.0.AND.FOLDER1_DESCRIP(J+1:J+1).NE.'=') THEN
+                 FOLDER1_DESCRIP = FOLDER1_DESCRIP(:J-1)
+              END IF
+	      IF (F1_START.LE.F1_NBULL) THEN
+                 NEWS_FOLDER1_NUMBER = FOLDER1_NUMBER
+		 CALL NEWS_GET_NEWEST_MESSAGE1(NEWS_NEW)
+	         WRITE (6,1015) '*'//FOLDER1_DESCRIP(:FLEN-1),
+     &					F1_START,F1_NBULL,NEWS_NEW-1
+              ELSE
+	         WRITE (6,1015) ' '//FOLDER1_DESCRIP(:FLEN-1),0,0,0
+	      END IF
+	   ELSE
+	      IF (F1_NBULL.GT.0) THEN
+	         CALL SYS$ASCTIM(,DATETIME,F1_NEWEST_BTIM,)
+	      ELSE
+	         DATETIME = '      NONE'
+	      END IF
+	      WRITE (6,1030) FOLDER1,DATETIME(:17),F1_NBULL,
+     &							FOLDER1_OWNER
+	   END IF
+	   NUM_FOLDER = NUM_FOLDER + 1
+	   IF (I.NE.NUM_FOLDERS.AND.PAGING.AND.((NUM_FOLDER+6.EQ.PAGE_LENGTH
+     &		.AND.I.EQ.NUM_FOLDER).OR.(NUM_FOLDER+2.EQ.PAGE_LENGTH.AND.
+     &		I.NE.NUM_FOLDER))) THEN
+	      NUM_FOLDER = 0
+	      WRITE(6,1080)	! Ask for input to proceed to next page
+	      CALL GET_INPUT_NOECHO_PROMPT(DATETIME(:1),
+     &			'HIT any key for next page....')
+	   END IF
+	  END DO
+	  IF (NUM_FOLDERS.EQ.0) THEN
+	     WRITE (6,1050)
+	     INDEX_COUNT = 0
+	     RETURN
+	  END IF
+	  WRITE (6,1060)
+	  FOLDER_Q = FOLDER_Q1			! Init queue pointer to header
+	  INDEX_COUNT = 2
+	  DIR_COUNT = 0
+	  RETURN
+	ELSE IF (INDEX_COUNT.EQ.2) THEN
+	 READ_TAG = IREAD_TAG
+	 IF (DIR_COUNT.LE.0) THEN
+	  F1_NBULL = 0
+	  DIR_COUNT = 0
+	  DO WHILE (NUM_FOLDERS.GT.0.AND.F1_NBULL.EQ.0)
+	     NUM_FOLDERS = NUM_FOLDERS - 1
+	     CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER1_COM)
+	     IF (F1_NBULL.GT.0) THEN
+	      FOLDER_NUMBER = -1
+	      CALL SELECT_FOLDER(.FALSE.,IER)
+	      IF (.NOT.IER) F1_NBULL = 0
+	     END IF
+	  END DO
+
+	  IF (F1_NBULL.EQ.0) THEN
+	     WRITE (6,1050)
+	     INDEX_COUNT = 0
+	     RETURN
+	  END IF
+	 END IF
+     
+	 IF (READ_TAG) THEN
+	    CALL GET_FIRST_TAG(FOLDER_NUMBER,IER,BULL_POINT)
+	 ELSE IF (INEW) THEN
+	    NEW = INEW
+            IF (REMOTE_SET.GE.3) THEN
+	       CALL NEWS_GET_NEWEST_MESSAGE(IER)
+	       IF (IER.GT.0.AND.IER.LE.F_NBULL) BULL_POINT = IER - 1	
+	    ELSE
+	       CALL FIND_NEWEST_BULL
+	    END IF
+	 END IF
+
+	 IF (INCMD(:4).NE.'INDE') THEN 
+	    IER = CLI$DCL_PARSE('INDEX',BULLETIN_SUBCOMMANDS)
+	 END IF
+
+	 CALL DIRECTORY(DIR_COUNT)
+	 IF (DIR_COUNT.GT.0) RETURN
+
+	 IF (NUM_FOLDERS.GT.0) THEN
+	    WRITE (6,1040)
+	 ELSE
+	    INDEX_COUNT = 0
+	 END IF
+	END IF
+
+	RETURN
+
+1000	FORMAT (' The following folders are present'/)
+1010	FORMAT (' The following folders with new messages are present'/)
+1015    FORMAT(1X,A<FLEN>,<PAGE_WIDTH-FLEN-36-1>X,2X,I10,2X,I10,2X,I10)
+1030	FORMAT(1X,A26,2X,A17,2X,I8,2X,A12)
+1035	FORMAT (1X,A,1X,I6)
+1040	FORMAT (' Type Return to continue to the next folder...')
+1050	FORMAT (' End of folder search.')
+1060	FORMAT (' Type Return to continue...')
+1080	FORMAT(' ',/)
+
+	END
+
+
+
+
+
+	SUBROUTINE SHOW_USER
+C
+C  SUBROUTINE SHOW_USER
+C
+C  FUNCTION: Shows information for specified users.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /POINT/ BULL_POINT
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+	COMMON /CTRLC_FLAG/ FLAG
+
+	DIMENSION NOLOGIN_BTIM(2),START_BTIM(2)
+
+	CHARACTER DATETIME*17
+
+	DIMENSION LAST(2,FOLDER_MAX)
+	INTEGER*2 LAST2(4,FOLDER_MAX)
+	EQUIVALENCE (LAST,LAST2)
+
+	ALL = CLI$PRESENT('NOLOGIN').OR.CLI$PRESENT('ALL')
+     &				.OR.CLI$PRESENT('LOGIN')
+
+	SETPRV = SETPRV_PRIV()		! SETPRV_PRIV rewrites TEMP_USER
+
+	IF (.NOT.ALL) THEN
+	   IER = CLI$GET_VALUE('USERNAME',TEMP_USER)
+	   IF (.NOT.IER) TEMP_USER = USERNAME
+	END IF
+
+	IF (.NOT.SETPRV.AND.(ALL.OR.USERNAME.NE.TEMP_USER)) THEN
+	   WRITE (6,'('' ERROR: No privs to use command.'')')
+	   RETURN
+	END IF
+
+	CALL SYS_BINTIM('5-NOV-2956 00:00:00.00',NOLOGIN_BTIM)
+
+	FOLDER_PRESENT = CLI$PRESENT('FOLDER')
+
+	IF (FOLDER_PRESENT) THEN
+	   IER = CLI$GET_VALUE('FOLDER',FOLDER1_NAME)
+	   IF (.NOT.IER) FOLDER1_NAME = FOLDER_NAME
+	   NEWS = INDEX(FOLDER1_NAME,'.').GT.0.OR.(FOLDER1_NAME(:1)
+     &			.GE.'a'.AND.FOLDER1_NAME(:1).LE.'z')
+           IF (.NOT.NEWS) THEN
+	      CALL OPEN_BULLFOLDER_SHARED
+	   ELSE
+	      CALL OPEN_BULLNEWS_SHARED
+	      CALL LOWERCASE(FOLDER1_NAME)
+	   END IF
+	   CALL READ_FOLDER_FILE_KEYNAME_TEMP
+     &				(FOLDER1_NAME(:TRIM(FOLDER1_NAME)),IER)
+	   CALL CLOSE_BULLFOLDER
+	   IF (IER.NE.0) THEN
+	      WRITE (6,'('' ERROR: Folder not found.'')')
+	      RETURN
+	   END IF
+	END IF
+
+	SINCE = CLI$PRESENT('SINCE').OR.CLI$PRESENT('START')
+	IF (CLI$GET_VALUE('SINCE',BULL_PARAMETER,LEN_P)) THEN
+	   IF (.NOT.NEWS) THEN
+	      IER = SYS_BINTIM(BULL_PARAMETER,START_BTIM)
+	      IF (.NOT.IER) THEN
+	         WRITE (6,'('' ERROR: Invalid date specified.'')')
+		 RETURN
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: /SINCE not valid with NEWS group.'')')
+	      RETURN
+	   END IF
+	ELSE IF (CLI$GET_VALUE('START',BULL_PARAMETER,LEN_P)) THEN
+	   IF (NEWS) THEN
+	      IER = OTS$CVT_TI_L(BULL_PARAMETER(:LEN_P),
+     &				    STARTMSG,,%VAL(1))
+	      IF (.NOT.IER) THEN
+		 WRITE (6,'('' ERROR: Invalid number specified.'')')
+		 RETURN
+	      END IF
+	   ELSE
+	      WRITE (6,'('' ERROR: /START not valid with folder.'')')
+	      RETURN
+	   END IF
+	ELSE IF (SINCE) THEN
+	   IF (BULL_POINT.EQ.0) THEN
+	      WRITE (6,'('' ERROR: No current message.'')')
+	      RETURN
+	   ELSE IF (NEWS) THEN
+	      STARTMSG = BULL_POINT
+	   ELSE
+	      START_BTIM(1) = MSG_BTIM(1)
+	      START_BTIM(2) = MSG_BTIM(2)
+	   END IF
+	ELSE IF (.NOT.NEWS) THEN
+	   CALL SYS_BINTIM('6-NOV-1956 00:00:00.00',START_BTIM)
+	ELSE
+	   STARTMSG = 1
+	END IF
+
+	CALL DISABLE_CTRL
+	CALL DECLARE_CTRLC_AST
+	IF (FOLDER_PRESENT) THEN
+	   CALL OPEN_BULLINF_SHARED
+	   IER = 0
+	   DO WHILE (IER.EQ.0.AND.FLAG.NE.1)
+	      IF (ALL) THEN
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,IOSTAT=IER) TEMP_USER,LAST
+	         END DO
+	      ELSE
+		 IF (NEWS) THEN
+		    LU = TRIM(TEMP_USER)
+		    TEMP_USER(LU:LU) = CHAR(128.OR.ICHAR(TEMP_USER(LU:LU)))
+		    IF (LU.GT.1) THEN
+		       TEMP_USER(LU-1:LU-1) =
+     &			        CHAR(128.OR.ICHAR(TEMP_USER(LU-1:LU-1)))
+		    ELSE
+		       TEMP_USER(2:2) = CHAR(128.OR.ICHAR(TEMP_USER(2:2)))
+	 	    END IF
+	 	 END IF
+	         DO WHILE (REC_LOCK(IER))
+	            READ (9,KEY=TEMP_USER,IOSTAT=IER) TEMP_USER,LAST
+	         END DO
+	      END IF 
+	      UNLOCK 9
+	      IF (IER.EQ.0) THEN
+	         LU = TRIM(TEMP_USER)
+		 I = MAX(LU,2)
+		 DO WHILE (I.GT.0.AND..NOT.BTEST(ICHAR(TEMP_USER(I:I)),7))
+		    I = I - 1
+		 END DO
+		 IF (NEWS.AND.I.GE.LU.AND.I.NE.1.AND.
+     &		     BTEST(ICHAR(TEMP_USER(I-1:I-1)),7)) THEN
+		    TEMP_USER(I:I) = CHAR(ICHAR(TEMP_USER(I:I)).AND.127)
+		    TEMP_USER(I-1:I-1) =
+     &				 CHAR(ICHAR(TEMP_USER(I-1:I-1)).AND.127)
+		    I = 0
+		    NEWSMSG = 1
+		    DO WHILE (LAST2(1,NEWSMSG).NE.NEWS_FOLDER1_NUMBER
+     &					.AND.NEWSMSG.LE.FOLDER_MAX)
+		       NEWSMSG = NEWSMSG + 1
+	            END DO
+		    IF (NEWSMSG.LE.FOLDER_MAX) THEN
+		       FOUND = LAST(2,NEWSMSG).GE.STARTMSG
+		    ELSE
+		       FOUND = .FALSE.
+		    END IF
+		 ELSE IF (.NOT.NEWS.AND.I.EQ.0) THEN
+		    FOUND = COMPARE_BTIM
+     &			(START_BTIM,LAST(1,FOLDER1_NUMBER+1)).LE.0
+		 ELSE
+		    FOUND = .FALSE.
+		 END IF
+		 IF (FOUND.AND.NEWS) THEN
+	            WRITE (6,'(1X,A,'' latest message read '',
+     &			I<LOG10(REAL(LAST(2,NEWSMSG)))+1>,''.'')')
+     &			TEMP_USER(:TRIM(TEMP_USER)),LAST(2,NEWSMSG)
+		 ELSE IF (FOUND) THEN
+		    CALL SYS$ASCTIM(,DATETIME,LAST(1,FOLDER1_NUMBER+1),)
+	            WRITE (6,'(1X,A,'' latest message read '',A,''.'')')
+     &				TEMP_USER(:TRIM(TEMP_USER)),DATETIME
+		 ELSE IF (.NOT.ALL) THEN
+	            WRITE (6,'('' User has never read or not subscribed'',
+     &			'' to specified folder.'')')
+	         END IF
+	      END IF
+	      IF (.NOT.ALL) THEN
+		 IF (IER.NE.0) THEN
+		    WRITE (6,'('' User info does not exist.'')')
+		 END IF
+		 IER = 2
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLINF
+	ELSE IF (.NOT.ALL) THEN
+	   CALL OPEN_BULLUSER_SHARED
+	   CALL READ_USER_FILE_KEYNAME(TEMP_USER,IER)
+	   IF (IER.EQ.0) THEN
+	      IF (COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM).GE.0) THEN
+	         WRITE (6,'('' NOLOGIN set for specified user.'')')
+	      ELSE
+	         CALL SYS$ASCTIM(,DATETIME,LOGIN_BTIM,)
+	         WRITE (6,'('' User last logged in at '',A,''.'')')
+     &						DATETIME
+	      END IF
+	   ELSE
+	      WRITE (6,'('' Entry for specified user not found.'')')
+	   END IF
+	   CALL CLOSE_BULLUSER
+	ELSE
+	   CALL OPEN_BULLUSER_SHARED
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0.AND.FLAG.NE.1)
+	      CALL READ_USER_FILE(IER)
+	      IF (IER.EQ.0.AND.TEMP_USER(:1).NE.':'.AND.
+     &				TEMP_USER(:1).NE.'*') THEN
+		 IER1 = COMPARE_BTIM(LOGIN_BTIM,NOLOGIN_BTIM)
+		 IF (.NOT.CLI$PRESENT('LOGIN').AND.IER1.GE.0) THEN
+	            WRITE (6,'('' NOLOGIN set for '',A,''.'')')
+     &					TEMP_USER(:TRIM(TEMP_USER))
+		 ELSE IF (.NOT.CLI$PRESENT('NOLOGIN').AND.IER1.LT.0.AND.
+     &			  COMPARE_BTIM(START_BTIM,LOGIN_BTIM).LE.0) THEN
+	            CALL SYS$ASCTIM(,DATETIME,LOGIN_BTIM,)
+	            WRITE (6,'(1X,A,'' last logged in at '',A,''.'')')
+     &				TEMP_USER(:TRIM(TEMP_USER)),DATETIME
+		 END IF
+	      END IF
+	   END DO
+	   CALL CLOSE_BULLUSER
+	END IF
+	CALL CANCEL_CTRLC_AST
+	CALL ENABLE_CTRL
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE INIT_MESSAGE_ADD(IN_FOLDER,IN_FROM,IN_DESCRIP,IER)
+C
+C  SUBROUTINE INIT_MESSAGE_ADD
+C
+C  FUNCTION:  Opens specified folder in order to add message.
+C
+C  INPUTS:
+C	IN_FOLDER  - Character string containing folder name
+C	IN_FROM	   - Character string containing name of owner of message.
+C		     If empty, the message is searched for either a
+C		     Reply-to: field or a From: field.  If none, then
+C		     the owner of the process is used.  If IN_FROM
+C		     ends with a %, it is assumed that it is simply
+C		     the prefix that should be when responding to the
+C		     address via MAIL.  I.e. the PMDF interface sends
+C		     IN%, so when the From: field is found, the message
+C		     owner becomes IN%"from-address".
+C	IN_DESCRIP - Character string containing subject of message.
+C		     If empty, the message is searched for a line
+C		     which starts with "Subj:" or "Subject:".
+C  OUTPUTS:
+C	IER - Error status.  True if properly connected to folder.
+C		False if folder not found.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLFILES.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /BCP/ BULLCP
+	LOGICAL BULLCP
+
+	COMMON /MAIL_PROTOCOL/ PROTOCOL,LPRO
+	CHARACTER*12 PROTOCOL
+	DATA LPRO/0/
+
+	COMMON /DIGEST/ LDESCR,FIRST_BREAK
+
+	CHARACTER*(*) IN_FOLDER,IN_FROM,IN_DESCRIP
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /TEXT_PRESENT/ TEXT
+
+	COMMON /SAVE_IN/ SAVE_IN_DESCRIP,SAVE_IN_FROM
+	CHARACTER*(INPUT_LENGTH) SAVE_IN_DESCRIP,SAVE_IN_FROM
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /OLD_BUFFER/ OLD_BUFFER_FROM,OLD_BUFFER_SUBJ
+	DATA OLD_BUFFER_FROM /.FALSE./, OLD_BUFFER_SUBJ /.FALSE./
+
+	COMMON /SCRTYPE/ SCRTYPE,SCRNAME
+	CHARACTER*132 SCRNAME
+	DATA SCRTYPE/-1/
+
+	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
+	CHARACTER*64 BULL_PARAMETER
+
+        COMMON /MAIN_FOLDER_DIRECTORY/ FOLDER1_DIRECTORY
+        CHARACTER*80 FOLDER1_DIRECTORY
+
+	IER = LIB$SYS_TRNLOG('BULL_DISABLE',LEN_P,BULL_PARAMETER)
+	IF (IER.EQ.1.AND.LEN_P.GT.0
+     &	    .AND.BULL_PARAMETER(:LEN_P).NE.'ENABLE') CALL SYS$DELPRC(,)
+
+	BULLCP = 1			! Inhibit folder cleanup subprocess
+
+	CALL CHECK_DIR_ACCESS()
+
+	CALL INIT_COMPRESS
+
+	FOLDER1_DIRECTORY = FOLDER_DIRECTORY
+
+	IER = 1
+	DO WHILE (IER.NE.0)
+	   CALL OPEN_BULLFOLDER			! Get folder file
+
+	   CALL READ_FOLDER_FILE_KEYNAME(IN_FOLDER(:TRIM(IN_FOLDER)),IER)
+
+	   CALL CLOSE_BULLFOLDER
+
+	   IF (IER.NE.0) THEN
+	      IER1 = 1
+	      DO WHILE (IER1)
+	         IER2 = SYS_TRNLNM_SYSTEM_INDEX('BULL_DIR_LIST',
+     &			   FOLDER_DIRECTORY)
+	         IF (IER2.AND.FOLDER_DIRECTORY.EQ.FOLDER1_DIRECTORY) THEN 
+		    IER1 = 1
+	         ELSE
+		    IER1 = 0
+		 END IF
+      	      END DO
+	      IF (IER2) THEN
+		 CALL ADD_DIRECTORIES
+	      ELSE
+		 CALL ERRSNS(IDUMMY,IER)
+	         RETURN
+	      END IF
+	   END IF
+	END DO
+	IER = 1
+
+        FOLDER_NAME = FOLDER
+
+	ENTRY INIT_MESSAGE_ADD_BBOARD(IN_FROM,IN_DESCRIP,IER)
+
+	LDESCR = 0
+
+	TEXT = .FALSE.			! No text written, as of yet
+
+	FIRST_BREAK = .TRUE.
+
+	IF (FOLDER_NUMBER.EQ.0) THEN	! If GENERAL folder
+	   FOLDER_SET = .FALSE.		! indicate it
+	ELSE				! Else it's another folder
+	   FOLDER_SET = .TRUE.		! indicate it
+	END IF
+
+	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//
+     &		FOLDER			! set folder file names
+
+	ENTRY INIT_MESSAGE_ADD_DIGEST(IN_FROM,IN_DESCRIP,IER)
+
+	CALL OPEN_BULLDIR		! Open directory file
+
+	CALL OPEN_BULLFIL		! Open data file
+
+	CALL READDIR(0,IER1)		! Get NBLOCK
+	IF (IER1.EQ.0) NBLOCK = 0	! If new file, NBLOCK is 0
+
+	NBLOCK = NBLOCK + 1
+	LENGTH = NBLOCK			! Initialize line count
+	IF (NEWS_FEED()) THEN
+	   CALL STRIP_HEADER(' ',-1,IER)
+	END IF
+
+	LEN_FROM = TRIM(IN_FROM)
+
+	IF (IN_FROM(LEN_FROM:LEN_FROM).EQ.'%') THEN	! Just protocol
+	   PROTOCOL = IN_FROM(:LEN_FROM)//'"'
+	   LPRO = LEN_FROM + 1
+	   LEN_FROM = 0
+	END IF
+
+	MAIL = BTEST(FOLDER_FLAG,11).AND.INDEX(FOLDER_DESCRIP,'<').GT.0
+	IF (MAIL) THEN 
+	   SCRNAME = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//'BULL.MAIL'
+	   OPEN (UNIT=3,DISPOSE='DELETE',FILE=SCRNAME,
+     &	    FORM='FORMATTED',RECL=LINE_LENGTH,IOSTAT=IER1,STATUS='NEW')
+	   SCRTYPE = 0
+	   SAVE_IN_DESCRIP = IN_DESCRIP
+	   SAVE_IN_FROM = ' '
+	ELSE IF (NEWS_FEED().OR.LEN_FROM.EQ.0
+     &		.OR.(BTEST(FOLDER_FLAG,5).AND.FIRST_BREAK)) THEN
+	   SCRTYPE = 0
+	   SCRNAME = 'SYS$LOGIN:BULL.SCR'
+	   OPEN (UNIT=3,DISPOSE='DELETE',FILE=SCRNAME,
+     &	    FORM='FORMATTED',RECL=LINE_LENGTH,IOSTAT=IER1,STATUS='NEW')
+	   IF (IER1.NE.0) THEN
+	      SCRNAME = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//'BULL.SCR'
+	      OPEN (UNIT=3,DISPOSE='DELETE',FILE=SCRNAME,
+     &		FORM='FORMATTED',RECL=LINE_LENGTH,STATUS='NEW')
+	   END IF
+	   SAVE_IN_DESCRIP = IN_DESCRIP
+	   SAVE_IN_FROM = ' '
+	END IF
+
+	IF (LEN_FROM.GT.0) THEN
+	   INFROM = IN_FROM
+	   IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	      CALL STORE_FROM(INFROM,LEN_FROM)
+	   ELSE	IF (INDEX(INFROM,'%"').GT.0) THEN	! Store any protocol
+	      LPRO = INDEX(INFROM,'%"') + 1
+	      PROTOCOL = INFROM(:LPRO)
+	   END IF
+	   LEN_DESCRP = TRIM(IN_DESCRIP)
+	   IF (LEN_DESCRP.GT.0) THEN
+	      INDESCRIP = IN_DESCRIP
+	      IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	         CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	      END IF
+	   ELSE
+	      DESCRIP = ' '
+	   END IF
+	END IF
+
+	OLD_BUFFER = ' '
+
+	OLD_BUFFER_SUBJ = .FALSE.
+	OLD_BUFFER_FROM = .FALSE.
+
+	INEXDATE = .FALSE.
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE WRITEOUT_STORED
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLDIR.INC'
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /STORED/ STORED
+
+	CHARACTER*256 BUFFER
+
+	REWIND (UNIT=3)
+
+      	IER = 0
+	DO WHILE (IER.EQ.0)
+	   READ (3,'(A)',IOSTAT=IER) BUFFER
+	   IF (IER.EQ.0) THEN
+	      CALL WRITE_MESSAGE_LINE(BUFFER)
+	   END IF
+	END DO
+
+	IF (BTEST(FOLDER_FLAG,5)) RETURN
+	IF (.NOT.NEWS_FEED().AND.
+     &	    .NOT.BTEST(FOLDER_FLAG,11).AND..NOT.STORED) CLOSE (UNIT=3)
+        IF (BTEST(FOLDER_FLAG,11)) REWIND (UNIT=3)
+
+	RETURN
+	END
+
+
+
+	SUBROUTINE WRITE_MESSAGE_LINE(BUFFER)
+C
+C  SUBROUTINE WRITE_MESSAGE_LINE
+C
+C  FUNCTION:  Writes one line of message into folder.
+C
+C  INPUTS:
+C	BUFFER - Character string containing line to be put into message.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /MAIL_PROTOCOL/ PROTOCOL,LPRO
+	CHARACTER*12 PROTOCOL
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /DIGEST/ LDESCR,FIRST_BREAK
+	DATA FIRST_BREAK/.TRUE./
+
+	COMMON /TEXT_PRESENT/ TEXT
+
+	COMMON /SAVE_IN/ SAVE_IN_DESCRIP,SAVE_IN_FROM
+	CHARACTER*(INPUT_LENGTH) SAVE_IN_DESCRIP,SAVE_IN_FROM
+
+	CHARACTER*(*) BUFFER
+
+	COMMON /LAST_BUFFER/ OLD_BUFFER
+	CHARACTER*(INPUT_LENGTH) OLD_BUFFER
+
+	COMMON /OLD_BUFFER/ OLD_BUFFER_FROM,OLD_BUFFER_SUBJ
+
+	COMMON /DATE/ DATE_LINE
+	CHARACTER*(INPUT_LENGTH) DATE_LINE
+
+	CHARACTER*24 TODAY
+
+	COMMON /STORED/ STORED
+	DATA STORED /.FALSE./ 
+
+	LEN_BUFFER = TRIM(BUFFER)
+
+	IF (LEN_FROM.EQ.0) THEN
+	   WRITE (3,'(A)') BUFFER(:MIN(LEN_BUFFER,LINE_LENGTH))
+	   IF (LEN_BUFFER.GT.LINE_LENGTH) THEN
+	      WRITE (3,'(A)') ' '//BUFFER(LINE_LENGTH+1:LEN_BUFFER)
+	   END IF
+	   IF (OLD_BUFFER_FROM.AND.(BUFFER(:1).EQ.' '.OR.
+     &		BUFFER(:1).EQ.CHAR(9)).AND.LEN_BUFFER.GT.1) THEN
+	      SAVE_IN_FROM = 
+     &		SAVE_IN_FROM(:TRIM(SAVE_IN_FROM))//BUFFER(:LEN_BUFFER)
+	      RETURN
+	   ELSE IF (OLD_BUFFER_SUBJ.AND.(BUFFER(:1).EQ.' '.OR.
+     &		BUFFER(:1).EQ.CHAR(9)).AND.LEN_BUFFER.GT.1) THEN
+	      INDESCRIP = 
+     &		INDESCRIP(:TRIM(INDESCRIP))//BUFFER(:LEN_BUFFER)
+	      LDESCR = LDESCR + LEN_BUFFER
+	      RETURN
+	   ELSE IF (BUFFER(:5).EQ.'From:'.AND.SAVE_IN_FROM.EQ.' ') THEN
+	      IF (LEN_BUFFER.GE.7) SAVE_IN_FROM = BUFFER(7:)
+	      OLD_BUFFER_FROM = .TRUE.
+	      OLD_BUFFER_SUBJ = .FALSE.
+	      RETURN
+	   ELSE IF (BUFFER(:9).EQ.'Subject: ') THEN
+	      LDESCR = LEN_BUFFER - 9
+	      INDESCRIP = BUFFER(10:)
+	      OLD_BUFFER_SUBJ = .TRUE.
+	      OLD_BUFFER_FROM = .FALSE.
+	      RETURN
+	   ELSE IF (BUFFER(:9).EQ.'Reply-To:') THEN
+	      IF (LEN_BUFFER.GE.11) SAVE_IN_FROM = BUFFER(11:)
+	      OLD_BUFFER_FROM = .TRUE.
+	      OLD_BUFFER_SUBJ = .FALSE.
+	      RETURN
+	   ELSE IF (LEN_BUFFER.EQ.0) THEN
+	      IF (SAVE_IN_FROM.EQ.' ') CALL GETUSER(SAVE_IN_FROM)
+	      LEN_FROM = TRIM(SAVE_IN_FROM)
+	      IF (LEN_FROM.GT.0) THEN
+		 OLD_BUFFER_FROM = .FALSE.
+		 INFROM = SAVE_IN_FROM
+		 IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+		    CALL STORE_FROM(INFROM,LEN_FROM)
+		 ELSE IF (INDEX(INFROM,'%"').GT.0) THEN
+		    LPRO = INDEX(INFROM,'%"') + 1
+		    PROTOCOL = INFROM(:LPRO)
+		 END IF
+		 IF (LDESCR.GT.0) THEN
+		    LEN_DESCRP = LDESCR
+	            CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+		 ELSE
+	            LEN_DESCRP = TRIM(SAVE_IN_DESCRIP)
+	            IF (LEN_DESCRP.GT.0) THEN
+	               INDESCRIP = SAVE_IN_DESCRIP
+	               IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	                  CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	               END IF
+	            ELSE
+		       INDESCRIP = ' '
+		       DESCRIP = ' '
+		    END IF
+		 END IF
+	         STORED = .TRUE.
+	         IF (.NOT.BTEST(FOLDER_FLAG,5)) CALL WRITEOUT_STORED
+	         STORED = .FALSE.
+	      END IF
+	   END IF
+	   OLD_BUFFER_FROM = .FALSE.
+	   OLD_BUFFER_SUBJ = .FALSE.
+	   RETURN
+	END IF
+	IF (BTEST(FOLDER_FLAG,5)) THEN
+	   IF (INDEX(BUFFER,'-------------').EQ.1) THEN
+	      BREAK = .TRUE.
+	      DO I=1,LEN_BUFFER
+		 IF (BUFFER(I:I).NE.'-') BREAK = .FALSE.
+	      END DO
+	   ELSE
+	      BREAK = .FALSE.
+	   END IF
+	   IF (BREAK) THEN
+	      IF (.NOT.FIRST_BREAK) THEN
+		 CALL FINISH_MESSAGE_ADD
+	         CALL INIT_MESSAGE_ADD_DIGEST(INFROM,INDESCRIP,IER)
+	      ELSE
+		 FIRST_BREAK = .FALSE.
+                 CLOSE (UNIT=3)
+	      END IF
+	      LFROM = 0
+	      LDESCR = 0
+	      RETURN
+	   ELSE IF (.NOT.FIRST_BREAK) THEN
+	      IF (LDESCR.EQ.0) THEN
+	         IF (BUFFER(:9).EQ.'Subject: ') THEN
+		    LDESCR = LEN_BUFFER - 9
+	            CALL STORE_DESCRP(BUFFER(10:),LDESCR)
+		    IF (LFROM.EQ.0) THEN
+		       LFROM = LEN_FROM
+	               CALL STORE_FROM(INFROM,LFROM)
+		    END IF
+		 ELSE IF (BUFFER(:6).EQ.'From: ') THEN
+		    LFROM = LEN_BUFFER - 6
+		    IF (LFROM.LE.0) THEN
+		       LFROM = TRIM(SAVE_IN_FROM)
+		       IF (LPRO.GT.0) THEN
+		          LFROM = LFROM + LPRO + 1
+	                  CALL STORE_FROM(PROTOCOL(:LPRO)//
+     &			   SAVE_IN_FROM//'"',LFROM)
+		       ELSE
+	                  CALL STORE_FROM(SAVE_IN_FROM,LFROM)
+		       END IF
+		    ELSE IF (LPRO.GT.0) THEN
+		       LFROM = LFROM + LPRO + 1
+	               CALL STORE_FROM(PROTOCOL(:LPRO)//
+     &			BUFFER(7:LEN_BUFFER)//'"',LFROM)
+		    ELSE
+	               CALL STORE_FROM(BUFFER(7:),LFROM)
+		    END IF
+		 END IF
+		 RETURN
+	      END IF
+	   ELSE
+	      IF (LEN_BUFFER.GT.0) THEN
+		 IF (.NOT.TEXT) THEN
+	            IF (.NOT.NEWS_FEED()) THEN
+		       TEXT = .TRUE.
+		    ELSE
+	               CALL STRIP_HEADER(BUFFER,TRIM(BUFFER),IER)
+		       TEXT = .NOT.IER
+		    END IF
+		 END IF
+		 IF (TEXT) THEN
+	            WRITE (3,'(A)') BUFFER(:MIN(LEN_BUFFER,LINE_LENGTH))
+		 END IF
+	      ELSE
+		 IF (TEXT) WRITE (3,'(A)') ' '
+	      END IF
+	      RETURN
+	   END IF
+	END IF
+
+	IF (LEN_BUFFER.EQ.0) THEN		! If empty line
+	   IF (.NOT.STORED.AND.
+     &	       ((TEXT.AND.NEWS_FEED()).OR.BTEST(FOLDER_FLAG,11))) THEN
+	      WRITE (3,'(A)') ' '
+	   END IF
+	   CALL STORE_BULL(1,' ',NBLOCK)
+	ELSE
+	   IF (LEN_DESCRP.EQ.0) THEN
+	      IF (BUFFER(:9).EQ.'Subject: ') THEN
+		 DESCRIP = BUFFER(INDEX(BUFFER,' ')+1:)
+		 LEN_DESCRP = LEN_BUFFER
+	      END IF
+	   END IF
+	   IF (.NOT.INEXDATE) THEN
+	      IF (BUFFER(:9).EQ.'Expires: '.OR.
+     &		  BUFFER(:11).EQ.'X-Expires: ') THEN
+		 I = INDEX(BUFFER,' ')+1
+		 NODATE = .FALSE.
+		 DO J=I,LEN_BUFFER
+		    IF (BUFFER(J:J).EQ.','.OR.BUFFER(J:J).EQ.'-') THEN
+		       BUFFER(J:J) = ' '
+		    END IF
+		 END DO
+	         CALL STR$UPCASE(BUFFER(I:),BUFFER(I:))
+		 NODATE = .TRUE.
+		 I = INDEX(BUFFER,' ')+1
+		 EXDATE(3:3) = '-'
+		 EXDATE(7:7) = '-'
+		 DO WHILE (I.LE.LEN_BUFFER)
+		    IF (BUFFER(I:I).GE.'0'.AND.BUFFER(I:I).LE.'9') THEN
+		       IF (NODATE) THEN
+			  IF (INDEX(BUFFER(I:),' ').EQ.2) THEN
+			     EXDATE(1:2) = '0'//BUFFER(I:I)
+			     I = I + 1
+			  ELSE
+			     EXDATE(1:2) = BUFFER(I:I+1)
+			     I = I + 2
+			  END IF
+			  NODATE = .FALSE.
+		       ELSE
+			  IF (LEN_BUFFER-I.EQ.1.OR.
+     &			     INDEX(BUFFER(I:),' ').EQ.3) THEN   ! No century?
+			     IER = SYS$ASCTIM(,TODAY,,)	   ! Get today's date
+			     YEAR = INDEX(TODAY(6:),'-')
+			     EXDATE(8:) = TODAY(6+YEAR:7+YEAR)//BUFFER(I:I+1)
+			     I = I + 2
+			  ELSE
+			     EXDATE(8:) = BUFFER(I:I+3)
+			     I = I + 4
+			  END IF
+		       END IF
+		    ELSE IF (BUFFER(I:I).GE.'A'.AND.BUFFER(I:I).LE.'Z') THEN
+		       EXDATE(4:6) = BUFFER(I:I+2)
+		       I = I + 3
+		    ELSE
+		       I = I + 1
+		    END IF
+		 END DO
+		 INEXDATE = .TRUE.
+	      END IF
+	   END IF
+	   CALL STORE_BULL(MIN(LEN_BUFFER,LINE_LENGTH),BUFFER,NBLOCK)
+	   IF (NEWS_FEED().AND..NOT.TEXT) THEN
+	      CALL STRIP_HEADER(BUFFER,TRIM(BUFFER),IER)
+	      TEXT = .NOT.IER
+	   ELSE
+	      TEXT = .TRUE.
+           END IF
+	   IF (.NOT.STORED.AND.
+     &	       ((TEXT.AND.NEWS_FEED()).OR.BTEST(FOLDER_FLAG,11))) THEN
+	      WRITE (3,'(A)') BUFFER(:MIN(LEN_BUFFER,LINE_LENGTH))
+	   END IF
+	END IF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE FINISH_MESSAGE_ADD
+C
+C  SUBROUTINE FINISH_MESSAGE_ADD
+C
+C  FUNCTION:  Writes message entry into directory file and closes folder
+C
+C  NOTE:  Only should be run if INIT_MESSAGE_ADD was successful.
+C
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /DIGEST/ LDESCR,FIRST_BREAK
+
+	COMMON /SCRTYPE/ SCRTYPE,SCRNAME
+	CHARACTER*132 SCRNAME
+
+	COMMON /TEXT_PRESENT/ TEXT
+
+	COMMON /MAIN_HEADER_INFO/ INFROM,INDESCRIP,LEN_FROM,LEN_DESCRP
+	COMMON /MAIN_HEADER_INFO/ INEXDATE
+	CHARACTER*(INPUT_LENGTH) INFROM,INDESCRIP
+
+	COMMON /SAVE_IN/ SAVE_IN_DESCRIP,SAVE_IN_FROM
+	CHARACTER*(INPUT_LENGTH) SAVE_IN_DESCRIP,SAVE_IN_FROM
+
+	CHARACTER*24 TODAY
+
+	CHARACTER USER_SAVE*12,PROC_SAVE*12
+
+	DIMENSION BIN_EXTIME(2)
+
+	IF (TEXT.AND.BTEST(FOLDER_FLAG,5).AND.FIRST_BREAK) THEN
+	   IF (LEN_FROM.GT.0) THEN
+	      CALL STORE_FROM(INFROM,LEN_FROM)
+	   ELSE
+	      CALL GETUSER(FROM)
+	      INFROM = FROM
+	      LEN_FROM = TRIM(INFROM)
+	   END IF
+	   IF (LEN_DESCRP.GT.0) THEN
+	      CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	   END IF
+	   LDESCRP = 1
+	   FIRST_BREAK = .FALSE.
+	   CALL WRITEOUT_STORED
+	   CLOSE (UNIT=3)
+	ELSE IF (LEN_FROM.EQ.0) THEN
+	   CALL GETUSER(FROM)
+	   INFROM = FROM
+	   LEN_FROM = TRIM(INFROM)
+	   LEN_DESCRP = TRIM(SAVE_IN_DESCRIP)
+	   IF (LEN_DESCRP.GT.0) THEN
+	      INDESCRIP = SAVE_IN_DESCRIP
+	      IF (.NOT.BTEST(FOLDER_FLAG,5)) THEN
+	         CALL STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+	      END IF
+	   ELSE
+	      INDESCRIP = ' '
+	      DESCRIP = ' '
+	   END IF
+	   CALL WRITEOUT_STORED
+	END IF
+
+	CALL FLUSH_BULL(NBLOCK)
+
+	CALL CLOSE_BULLFIL			! Finished adding bulletin
+
+	IF ((BTEST(FOLDER_FLAG,5).AND.LDESCR.EQ.0).OR.	! End of digest msg
+     &				.NOT.TEXT) THEN	! or no message text found
+	   CALL CLOSE_BULLDIR			! then don't add message entry
+	   IF (SCRTYPE.EQ.0) THEN
+	      CLOSE (UNIT=3)
+              SCRTYPE = -1
+	   END IF
+	   RETURN
+	END IF
+
+	EXTIME = '00:00:00.00'
+	IF (INEXDATE) THEN
+	   IER = SYS_BINTIM(EXDATE//' '//EXTIME,BIN_EXTIME)
+	   IF (IER) THEN			! If good date format
+	      IER = SYS$ASCTIM(,TODAY,,)	! Get today's date
+	      IER = COMPARE_DATE(EXDATE,TODAY(:11)) ! Compare date with today's
+	      IF ((IER.GT.F_EXPIRE_LIMIT.AND.F_EXPIRE_LIMIT.GT.0) ! Too great?
+     &		.OR.IER.LE.0) THEN		! or expiration date not future
+	         INEXDATE = .FALSE.		! Don't use it
+	      END IF
+	   ELSE
+	      INEXDATE = .FALSE.		! Don't use it
+	   END IF
+	END IF
+
+	IF (.NOT.INEXDATE) THEN
+	   IF (FOLDER_BBEXPIRE.EQ.-1) THEN	! Folder has expiration time?
+	      EXDATE = '5-NOV-2100'		! no, so set date far in future
+	      SYSTEM = 2			! indicate permanent message
+	   ELSE					! Else set expiration date
+	      CALL GET_EXDATE(EXDATE,FOLDER_BBEXPIRE)
+	      SYSTEM = 0
+	   END IF
+	END IF
+
+	LENGTH = NBLOCK - LENGTH + 1		! Number of records
+
+	CALL ADD_ENTRY				! Add the new directory entry
+
+	CALL CLOSE_BULLDIR			! Totally finished with add
+
+	CALL UPDATE_FOLDER
+
+	IF (SCRTYPE.EQ.0.AND.NEWS_FEED()) THEN
+	   FOLDER1_DESCRIP = FOLDER_DESCRIP(INDEX(FOLDER_DESCRIP,'<')+1:)
+	   FOLDER1_DESCRIP = FOLDER1_DESCRIP(:INDEX(FOLDER1_DESCRIP,'>')-1)
+	   CALL SYS$SETAST(%VAL(1))
+	   CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
+      	   CALL NEWS_POST('ignore',.TRUE.,IER,INDESCRIP)
+	   IF (TEST_BULLCP().EQ.2) CALL SYS$SETAST(%VAL(0))
+	   IF (.NOT.BTEST(FOLDER_FLAG,11)) CLOSE (UNIT=3)
+	END IF
+
+	IF (BTEST(FOLDER_FLAG,11).AND.SCRTYPE.EQ.0) THEN
+	   IF (NEWS_FEED()) THEN
+	      SLIST = INDEX(FOLDER_DESCRIP,'[')
+	   ELSE
+	      SLIST = INDEX(FOLDER_DESCRIP,'<')
+	   END IF
+	   IF (SLIST.GT.0) THEN
+	      INPUT = FOLDER_DESCRIP(SLIST+1:)
+	      IF (NEWS_FEED()) THEN
+	         ILEN = INDEX(INPUT,']') - 1
+	      ELSE
+	         ILEN = INDEX(INPUT,'>') - 1
+	      END IF
+	      IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
+	      INPUT = INPUT(:ILEN)
+              CALL ADD_PROTOCOL(INPUT,ILEN)
+	      CLOSE (UNIT=3,STATUS='SAVE')
+	      CALL GETUSER(PROC_SAVE)
+              USER_SAVE = USERNAME
+	      USERNAME = FOLDER
+	      IF (CONFIRM_USER(USERNAME).EQ.0) THEN
+	        CALL SETUSER(USERNAME)
+	      END IF
+	      IF (SYS_TRNLNM('MX_NODE_NAME','DEFINED')) THEN
+	         IER = LIB$SET_LOGICAL
+     &			('MX_REPLY_TO',INFROM(:TRIM(INFROM)))
+	      ELSE IF (SYS_TRNLNM('PMDF_ROOT','DEFINED')) THEN 
+	         IER = LIB$SET_LOGICAL
+     &			('PMDF_REPLY_TO',INFROM(:TRIM(INFROM)))
+	      ELSE IF (FOLDER1_BBOARD(:4).NE.'NONE') THEN
+		 USERNAME = FOLDER_BBOARD
+	      END IF
+	      IF (.NOT.BTEST(FOLDER_FLAG,15)) THEN 
+	         CALL RESPOND_MAIL(SCRNAME,INPUT,
+     &	   	    FOLDER(:TRIM(FOLDER))//' folder message: '//
+     &	   	    INDESCRIP(:LEN_DESCRP),STATUS)
+	      ELSE
+	         CALL RESPOND_MAIL(SCRNAME,INPUT,
+     &	   	    INDESCRIP(:LEN_DESCRP),STATUS)
+	      END IF
+              CALL LIB$DELETE_FILE(SCRNAME(:TRIM(SCRNAME))//';*')
+	      CALL SETUSER(PROC_SAVE)
+	      USERNAME = USER_SAVE
+	   ELSE
+	      CLOSE (UNIT=3)
+	   END IF
+	ELSE IF (SCRTYPE.EQ.0) THEN
+	   CLOSE (UNIT=3)
+	END IF
+
+	CALL STRIP_HEADER(' ',-1,IER)
+
+	SCRTYPE = -1
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_FROM(IFROM,LEN_INFROM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	COMMON /MAIL_PROTOCOL/ PROTOCOL,LPRO
+	CHARACTER*12 PROTOCOL
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(*) IFROM
+
+	CHARACTER*(INPUT_LENGTH) INFROM
+
+	INFROM = IFROM
+
+	IF (LPRO.GT.0) THEN			! Protocol present?
+	   I = INDEX(INFROM,'%"') + 2		! Make usable for VMS MAIL
+	   IF (I.EQ.2) THEN
+	      INFROM = PROTOCOL(:LPRO)//INFROM(:LEN_INFROM)//'"'
+	      I = LPRO + 1
+	      LEN_INFROM = LEN_INFROM + LPRO + 1
+	   END IF
+	   DO WHILE (I.LT.LEN_INFROM)
+	      IF (INFROM(I:I).EQ.'"') THEN
+		 INFROM(I:I) = ''''
+	      ELSE IF (INFROM(I:I).EQ.'\') THEN
+		 INFROM(I+1:) = '\'//INFROM(I+1:)
+		 LEN_INFROM = LEN_INFROM + 1
+		 I = I + 1
+	      ELSE IF (INFROM(I:I).EQ.''''.AND.
+     &		       INDEX(INFROM,'@').GT.I) THEN
+		 INFROM(I:) = '\s'//INFROM(I+1:)
+		 LEN_INFROM = LEN_INFROM + 1
+		 I = I + 2
+	      END IF
+	      I = I + 1
+	   END DO
+	END IF
+
+	DO I=1,LEN_INFROM			! Remove control characters
+	   IF (INFROM(I:I).LT.' ') INFROM(I:I) = ' '
+	END DO
+
+	DO WHILE (LEN_INFROM.GT.0.AND.INFROM(:1).EQ.' ')
+	   INFROM = INFROM(2:)
+	   LEN_INFROM = LEN_INFROM - 1
+	END DO
+
+	TWO_SPACE = INDEX(INFROM,'  ')
+	DO WHILE (TWO_SPACE.GT.0.AND.TWO_SPACE.LT.LEN_INFROM)
+	   INFROM = INFROM(:TWO_SPACE)//INFROM(TWO_SPACE+2:)
+	   LEN_INFROM = LEN_INFROM - 1
+	   TWO_SPACE = INDEX(INFROM,'  ')
+	END DO
+
+C	IF (.NOT.NEWS_FEED()) THEN
+           CALL STORE_BULL(6+LEN_INFROM,'From: '//INFROM(:LEN_INFROM),
+     &		NBLOCK)
+C	END IF
+
+	IF (INDEX(INFROM,'%"').GT.0)		! Strip off protocol program
+     &		INFROM = INFROM(INDEX(INFROM,'%"')+2:)
+
+	IF (INDEX(INFROM,'::').GT.0)		! Strip off node name
+     &		INFROM = INFROM(INDEX(INFROM,'::')+2:)	! I.e. HOST::USER
+
+	CALL GET_FROM(FROM,INFROM,LEN_INFROM)
+
+	RETURN
+	END
+
+
+	SUBROUTINE GET_FROM(FROM,INFROM1,LEN_INFROM)
+
+	IMPLICIT INTEGER (A-Z)
+
+	CHARACTER*(*) INFROM1,FROM
+
+	CHARACTER*256 INFROM
+
+	INFROM = INFROM1
+
+	DO WHILE (INDEX(INFROM,'!').GT.0.AND.	! Unix address go backwards.
+     &		INDEX(INFROM,'!').LT.INDEX(INFROM,'@'))
+	   INFROM = INFROM(INDEX(INFROM,'!')+1:)	! I.e. host!user
+	END DO
+
+	I = INDEX(INFROM,'<')
+	IF (I.GT.0.AND.INDEX(INFROM(I+1:),'@').GT.0) THEN ! Name may be of form
+	   INFROM = INFROM(INDEX(INFROM,'<')+1:)   ! personal-name <net-name>
+	END IF
+
+	I = INDEX(INFROM,'(')
+	IF (I.GT.0.AND.INDEX(INFROM(I+1:),'@').GT.0) THEN ! Name may be of form
+	   INFROM = INFROM(INDEX(INFROM,'(')+1:)   ! personal-name (net-name)
+	END IF
+
+	I = 1	! Trim username to start at first alpha character
+	DO WHILE (I.LE.LEN_INFROM.AND.(INFROM(I:I).EQ.' '.OR.
+     &		INFROM(I:I).EQ.'%'.OR.INFROM(I:I).EQ.'.'.OR.
+     &		INFROM(I:I).EQ.'@'.OR.INFROM(I:I).EQ.'<'.OR.
+     &		INFROM(I:I).EQ.'\'.OR.INFROM(I:I).LE.' '.OR.
+     &		INFROM(I:I).GE.CHAR(127).OR.
+     &		INFROM(I:I).EQ.'"'.OR.INFROM(I:I).EQ.''''))
+	   I = I + 1
+	END DO
+	INFROM = INFROM(I:)
+	J = LEN_INFROM - I + 1
+
+	I = 1		! Trim username to end at a alpha character
+	DO WHILE (I.LE.J.AND.INFROM(I:I).NE.' '.AND.
+     &		INFROM(I:I).NE.'%'.AND.
+     &		INFROM(I:I).NE.'@'.AND.INFROM(I:I).NE.'<'.AND.
+     &		INFROM(I:I).NE.'\'.AND.INFROM(I:I).GT.' '.AND.
+     &		INFROM(I:I).LT.CHAR(127).AND.
+     &		INFROM(I:I).NE.'"'.AND.INFROM(I:I).NE.'''')
+	   I = I + 1
+	END DO
+	FROM = INFROM(:I-1)
+
+	DO J=2,TRIM(FROM)
+	   IF ((FROM(J:J).GE.'A'.AND.FROM(J:J).LE.'Z').AND.
+     &	       ((FROM(J-1:J-1).GE.'A'.AND.FROM(J-1:J-1).LE.'Z').OR.
+     &	        (FROM(J-1:J-1).GE.'a'.AND.FROM(J-1:J-1).LE.'z'))) THEN
+	      FROM(J:J) = CHAR(ICHAR(FROM(J:J))-ICHAR('A')+ICHAR('a'))
+	   END IF
+	END DO
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE STORE_DESCRP(INDESCRIP,LEN_DESCRP)
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	CHARACTER*(*) INDESCRIP
+
+	CALL CONVERT_TABS(INDESCRIP,LEN_DESCRP)
+
+	DO I=1,LEN_DESCRP			! Remove control characters
+	   IF (INDESCRIP(I:I).LT.' '.OR.ICHAR(INDESCRIP(I:I)).GT.126)
+     &			INDESCRIP(I:I) = ' '
+	END DO
+
+	DO WHILE (LEN_DESCRP.GT.0.AND.INDESCRIP(:1).EQ.' ')
+	   INDESCRIP = INDESCRIP(2:)
+	   LEN_DESCRP = LEN_DESCRP - 1
+	END DO
+
+	IF (LEN_DESCRP.GT.LEN(DESCRIP)) THEN
+C	IF (LEN_DESCRP.GT.LEN(DESCRIP).AND..NOT.NEWS_FEED()) THEN
+				! Is length > allowable subject length?
+	   CALL STORE_BULL(6+LEN_DESCRP,'Subj: '//
+     &		INDESCRIP(:LEN_DESCRP),NBLOCK)
+	END IF
+
+	DESCRIP = INDESCRIP(:MIN(LEN_DESCRP,LEN(DESCRIP)))
+
+	RETURN
+	END
+
+
+
+
+
+	SUBROUTINE STRIP_HEADER(BUFFER,BLEN,IER)
+C
+C  SUBROUTINE STRIP_HEADER
+C
+C  FUNCTION:  Indicates whether line is part of mail message header.
+C
+C  INPUTS:
+C	BUFFER	- Character string containing input line of message.
+C	BLEN	- Length of character string.  If = 0, initialize subroutine.
+C
+C  OUTPUTS:
+C	IER	- If true, line should be stripped.  Else, end of header.
+C
+	IMPLICIT INTEGER (A - Z)
+
+	INCLUDE 'BULLDIR.INC'
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	COMMON /DATE/ DATE_LINE
+	CHARACTER*(INPUT_LENGTH) DATE_LINE
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	COMMON /NEWSGROUPS/ NEWSGROUPS
+	CHARACTER*256 NEWSGROUPS
+
+	COMMON /HEADER_QUEUE/ HEADER_Q,HEADER_Q1,NHEAD
+	DATA HEADER_Q1/0/
+
+	CHARACTER*(*) BUFFER
+
+	IF (TRIM(BUFFER).EQ.0) THEN
+			! If STRIP not set for folder or empty line
+	   IER = .FALSE.
+	   CONT_LINE = .FALSE.
+	   LAST_NEWSGROUPS = .FALSE.
+	   CALL INIT_QUEUE(HEADER_Q1,INPUT)
+	   IF (BLEN.EQ.-1) THEN
+	      CALL INIT_QUEUE(HEADER_Q1,INPUT)
+	      HEADER_Q = HEADER_Q1
+	      NHEAD = 0
+	   END IF
+	   RETURN
+	END IF
+
+	IF (BLEN.EQ.0) THEN
+	   DATE_LINE = ' '
+	   CONT_LINE = .FALSE.
+	   LAST_NEWSGROUPS = .FALSE.
+	END IF
+
+	IER = .TRUE.
+
+	IF (CONT_LINE.AND.(BUFFER(:1).EQ.' '.OR.   ! If line is continuation
+     &		BUFFER(:1).EQ.CHAR(9))) THEN	   ! of previous header line
+	   IF (LAST_NEWSGROUPS) THEN
+	      NEWSGROUPS = NEWSGROUPS(:TRIM(NEWSGROUPS))//BUFFER(2:)
+	   END IF
+	   CALL WRITE_QUEUE(%VAL(HEADER_Q),HEADER_Q,BUFFER)
+	   NHEAD = NHEAD + 1
+	   RETURN
+	END IF
+
+	I = 1
+	DO WHILE (I.LE.BLEN.AND.BUFFER(I:I).NE.' ')
+	   IF (BUFFER(I:I).EQ.':') THEN	! Header line found
+	      CONT_LINE = .TRUE.	! Next line might be continuation
+	      LAST_NEWSGROUPS = .FALSE.
+	      IF (REMOTE_SET.LT.3.AND.BUFFER(:5).EQ.'Date:') THEN
+		 DATE_LINE = 'Message sent'//BUFFER(5:BLEN)
+		 IF (DATE_LINE(TRIM(DATE_LINE):).NE.'.') THEN
+		    DATE_LINE(TRIM(DATE_LINE)+1:) = '.'
+	         END IF
+	      ELSE IF (BUFFER(:11).EQ.'Newsgroups:') THEN
+		 NEWSGROUPS = BUFFER(13:)
+		 LAST_NEWSGROUPS = .TRUE.
+	      END IF
+	      CALL WRITE_QUEUE(%VAL(HEADER_Q),HEADER_Q,BUFFER)
+	      NHEAD = NHEAD + 1
+	      RETURN
+	   ELSE
+	      I = I + 1
+	   END IF
+	END DO
+
+	IER = .FALSE.
+	CONT_LINE = .FALSE.
+	LAST_NEWSGROUPS = .FALSE.
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE SET_NEWS_FOLDER_DEFAULT(NOTIFY,READNEW,BRIEF)
+C
+C  SUBROUTINE SET_NEWS_FOLDER_DEFAULT
+C
+C  FUNCTION: Sets flag defaults for specified news group
+C	Note: If NOTIFY READNEW and BRIEF = 0, it is either news 
+C	group removal or SET SUBSCRIBE command.
+C
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /COMMAND_LINE/ INCMD
+	CHARACTER*256 INCMD
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	EXTERNAL CLI$_NEGATED
+
+	ALL = .FALSE.
+	DEFAULT = 1
+        NODEFAULT = 0
+	SUB = ABS(BRIEF)+ABS(NOTIFY)+ABS(READNEW).EQ.0
+
+	IF (NOTIFY.EQ.1.AND.REMOTE_SET.EQ.3) THEN
+	   WRITE (6,'('' ERROR: /NOTIFY is invalid with non-stored'',
+     &		  '' news group.'')')
+           RETURN
+	END IF
+
+	IF (INCMD(:3).EQ.'SET') THEN
+	   IF (.NOT.SETPRV_PRIV()) THEN
+	      WRITE (6,'(
+     &           '' ERROR: Privileges needed for changing defaults.'')')
+	      RETURN
+	   END IF
+	   ALL = CLI$PRESENT('ALL')
+	   DEFAULT = CLI$PRESENT('DEFAULT')
+	   NODEFAULT = CLI$PRESENT('NODEFAULT')
+	   CALL OPEN_BULLNEWS_SHARED
+	   CALL OPEN_BULLINF_SHARED
+	   IF (CLI$PRESENT('NOPERMANENT').OR.CLI$PRESENT('PERMANENT').OR.
+     &	     	(SUB.AND.(NODEFAULT.OR.CLI$PRESENT('NOPERMANENT')))) THEN
+              DO WHILE (REC_LOCK(IER1))
+                 READ (9,KEY='*PERM',IOSTAT=IER1) TEMP_USER,INF_REC
+	      END DO
+	      IF (IER1.NE.0) THEN
+                 DO I=1,FOLDER_MAX
+                    INF_REC(1,I) = 0
+                    INF_REC(2,I) = 0
+                 END DO
+              END IF
+
+              IF (CLI$PRESENT('PERMANENT')) THEN
+                 CALL SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+		 IF (SUB) DEFAULT = 1
+              ELSE IF (CLI$PRESENT('NOPERMANENT').OR.NODEFAULT) THEN
+                 IF (NOTIFY.GE.0) CALL SET_NEWS_FLAG(IER,0,-1,-1)
+                 IF (READNEW.GE.0.OR.BRIEF.GE.0)
+     &	 		CALL SET_NEWS_FLAG(IER,-1,0,0)
+		 IF (SUB)
+     &			CALL SET_NEWS_FLAG(IER,-1,-1,-1)
+              END IF
+              IF (.NOT.IER) THEN
+                 CALL CLOSE_BULLNEWS
+                 CALL CLOSE_BULLINF
+                 RETURN
+              END IF
+              IF (IER1.EQ.0) THEN
+                 REWRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+              ELSE
+                 WRITE (9,IOSTAT=IER) '*PERM       ',INF_REC
+              END IF
+           END IF	
+	ELSE
+ 	   CALL OPEN_BULLNEWS_SHARED
+ 	   CALL OPEN_BULLINF_SHARED
+	END IF
+
+        DO WHILE (REC_LOCK(IER1))
+           READ (9,KEY='*DEFAULT',IOSTAT=IER1) TEMP_USER,INF_REC
+	END DO
+	IF (IER1.NE.0) THEN
+	   DO I=1,FOLDER_MAX
+	      INF_REC(1,I) = 0
+	      INF_REC(2,I) = 0
+	   END DO
+	END IF
+        IF (NODEFAULT.AND.SUB) THEN
+	   NOTIFY = -1
+	   READNEW = -1
+	   BRIEF = -1
+	END IF
+  	IF (DEFAULT.OR.NODEFAULT) THEN
+	   IF (NODEFAULT.AND..NOT.SUB) THEN
+	      IF (NOTIFY.NE.-1) CALL SET_NEWS_FLAG(IER,0,-1,-1)
+	      IF (READNEW.NE.-1.OR.BRIEF.NE.-1)
+     &		CALL SET_NEWS_FLAG(IER,-1,0,0)
+	   ELSE
+	      CALL SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+	   END IF
+           IF (.NOT.IER) THEN
+              CALL CLOSE_BULLNEWS
+              CALL CLOSE_BULLINF
+              RETURN
+           END IF
+	   IF (IER1.EQ.0) THEN
+	      REWRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+	   ELSE
+	      WRITE (9,IOSTAT=IER) '*DEFAULT    ',INF_REC
+	   END IF
+	END IF
+	IF ((ALL.OR.(SUB.AND.INCMD(:3).NE.'SET')).AND.IER.EQ.0) THEN
+	   CALL OPEN_BULLUSER_SHARED
+	   CALL READ_USER_FILE_HEADER(IER)
+	   CALL READ_USER_FILE(IER)
+	   DO WHILE (IER.EQ.0)
+	      IF (TEMP_USER(:1).NE.'*'.AND.TEMP_USER(:1).NE.':') THEN
+	         LU = TRIM(TEMP_USER)
+	         TEMP_USER(LU:LU) = CHAR(128.OR.ICHAR(TEMP_USER(LU:LU)))
+	         IF (LU.GT.1) THEN
+	            TEMP_USER(LU-1:LU-1) =
+     &			CHAR(128.OR.ICHAR(TEMP_USER(LU-1:LU-1)))
+	         ELSE
+	            TEMP_USER(2:2) = CHAR(128.OR.ICHAR(TEMP_USER(2:2)))
+	         END IF
+	         DO WHILE (REC_LOCK(IER1))
+                    READ (9,KEY=TEMP_USER,IOSTAT=IER1) TEMP_USER,INF_REC
+	         END DO
+       	         IF (IER1.NE.0) THEN
+	            DO I=1,FOLDER_MAX
+	               INF_REC(1,I) = 0
+	               INF_REC(2,I) = 0
+	            END DO
+	         END IF
+	         CALL SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+		 IF (IER1.EQ.0) THEN
+		    REWRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+		 ELSE
+	            WRITE (9,IOSTAT=IER) TEMP_USER,INF_REC
+		 END IF
+	      END IF
+	      CALL READ_USER_FILE(IER)
+ 	   END DO
+	   CALL CLOSE_BULLUSER
+	END IF
+
+	CALL CLOSE_BULLNEWS
+	CALL CLOSE_BULLINF
+
+	RETURN
+	END
+
+
+
+
+	SUBROUTINE READ_INF_REC
+
+	IMPLICIT INTEGER (A-Z)
+
+	INCLUDE 'BULLFOLDER.INC'
+
+	INCLUDE 'BULLUSER.INC'
+
+	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
+
+	CALL OPEN_BULLINF_SHARED
+        DO WHILE (REC_LOCK(IER1))
+           READ (9,KEY='*PERM',IOSTAT=IER1) TEMP_USER,INF_REC
+	END DO
+	IF (IER1.NE.0) THEN
+           DO I=1,FOLDER_MAX
+              INF_REC(1,I) = 0
+              INF_REC(2,I) = 0
+           END DO
+        END IF
+	CALL CLOSE_BULLINF
+
+	RETURN
+
+	ENTRY SET_NEWS_FLAG(IER,NOTIFY,READNEW,BRIEF)
+
+	I = 1
+	DO WHILE (INF_REC2(1,I).NE.NEWS_FOLDER_NUMBER.AND.
+     &		INF_REC2(1,I).NE.0.AND.I.LE.FOLDER_MAX-1)
+	   I = I + 1
+	END DO
+
+	IF (I.GT.FOLDER_MAX-1.AND.TEMP_USER(:1).EQ.'*') THEN
+	   WRITE (6,'('' ERROR: You have '',
+     &		    '' reached the news folder limit of '',I,''.'')')
+     &		    FOLDER_MAX-1
+	   IER = 0
+	   RETURN
+	END IF
+
+	IF (INF_REC2(1,I).EQ.NEWS_FOLDER_NUMBER) THEN
+	   IF (NOTIFY.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),13)
+	   IF (NOTIFY.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),13)
+	   IF (READNEW.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),14)
+	   IF (READNEW.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),14)
+	   IF (BRIEF.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),15)
+	   IF (BRIEF.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),15)
+  	   IF (NOTIFY+READNEW+BRIEF.EQ.-3) THEN
+	      DO J=I,FOLDER_MAX-2
+	         CALL COPY2(INF_REC(1,J),INF_REC(1,J+1))
+              END DO
+	   END IF
+	   IER = 1
+	   RETURN
+	END IF
+
+	IF (NOTIFY+READNEW+BRIEF.EQ.-3) RETURN
+
+	DO J=I,1,-1
+	   IF (J.GT.1) THEN
+	      CALL READ_FOLDER_FILE_KEYNUM_TEMP(
+     &	         ZEXT(INF_REC2(1,J-1)),IER)
+	      IF (FOLDER_DESCRIP.LT.FOLDER1_DESCRIP) THEN
+	         CALL COPY2(INF_REC(1,J),INF_REC(1,J-1))
+	      END IF
+	   END IF
+	   IF (FOLDER_DESCRIP.GT.FOLDER1_DESCRIP.OR.J.EQ.1) THEN
+	      INF_REC2(1,J) = NEWS_FOLDER_NUMBER
+	      IF (F_START.LE.F_NBULL) THEN
+		 INF_REC2(2,J) = MIN(8191,F_NBULL-(F_START-1))
+		 INF_REC(2,J) = F_START - 1
+	      ELSE
+		 INF_REC2(2,J) = 0
+		 INF_REC(2,J) = F_NBULL
+	      END IF
+	      IF (NOTIFY.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),13)
+	      IF (NOTIFY.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),13)
+	      IF (READNEW.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),14)
+	      IF (READNEW.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),14)
+	      IF (BRIEF.EQ.1) INF_REC2(2,I) = IBSET(INF_REC2(2,I),15)
+	      IF (BRIEF.EQ.0) INF_REC2(2,I) = IBCLR(INF_REC2(2,I),15)
+	      IER = 1
+	      RETURN
+	   END IF
+	END DO
+
+	RETURN
+	END
diff --git a/decus/vmslt98a/bulletin/bullfiles.inc b/decus/vmslt98a/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..0df9866c997645bd450919b1e2f85513c064a695
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullfiles.inc
@@ -0,0 +1,39 @@
+C
+C  FOLDER_DIRECTORY IS THE DIRECTORY THAT FILES FOR FOLDERS THAT
+C  ARE CREATED ARE KEPT IN.  IF YOU WISH TO PREVENT FOLDER CREATION,
+C  YOU SHOULD MODIFY BULLCOM.CLD TO MAKE THE CREATE COMMAND A PRIVILEGED
+C  COMMAND (OR SIMPLY REMOVE THE LINES WHICH DEFINE THE CREATE COMMAND).
+C
+C  BBOARD_DIRECTORY IS THE SCRATCH AREA USED BY BBOARD WHEN EXTRACTING
+C  MAIL.  IF IT IS UNDEFINED, BBOARD WILL NOT BE ABLE TO BE USED.
+C  NOTE THAT EITHER THE BBOARD ACCOUNTS MUST HAVE ACCESS TO THIS DIRECTORY,
+C  OR THE BBOARD ACCOUNTS MUST BE GIVEN SYSPRV PRIVILEGES TO BE ABLE
+C  TO WRITE INTO THIS DIRECTORY.  ALSO, FOR BBOARD TO WORK, MAKE SURE
+C  THAT THE SUBPROCESS LIMIT FOR USERS IS AT LEAST 2.  YOU WILL ALSO HAVE
+C  TO INCREASE THE FOLLOWING SYSTEM PARAMETERS WHICH AFFECT DETACHED PROCESES:
+C  PQL_DPGFLQUOTA = 15000, PQL_DWSQUOTA = 500, & PQL_DFILLM = 30.
+C  (NOTE: ACCESS CAN BE GIVEN TO THE DIRECTORY FOR THE BBOARD ACCOUNTS USING
+C  ACLS, I.E. " SET ACL/ACL=(ID=bboard,ACCESS=R+W)/OBJ=FILE directory.DIR")
+C
+	COMMON /FILES/ BULLFOLDER_FILE,FOLDER_DIRECTORY,BBOARD_DIRECTORY
+	COMMON /FILES/ BULLUSER_FILE,BULLINF_FILE,NEWS_DIRECTORY
+	COMMON /FILES/ BULLNEWS_FILE
+	CHARACTER*80 FOLDER_DIRECTORY /'BULL_DIR:'/
+	CHARACTER*80 BBOARD_DIRECTORY /'BULL_DIR:'/
+C
+C  NOTE: THE FOLLOWING FILE ARE STORED IN THE FOLDER_DIRECTORY BY DEFAULT.
+C  YOU CAN CHANGE THIS BY ADDING A DIRECTORY NAME TO THE FILE NAME.
+C
+	CHARACTER*80 BULLUSER_FILE /'BULLUSER.DAT'/	! Stores user login time
+							! & folder flag settings
+	CHARACTER*80 BULLFOLDER_FILE /'BULLFOLDER.DAT'/	! Stores folder data
+	CHARACTER*80 BULLINF_FILE /'BULLINF.DAT'/	! Stores times of last
+							! read messages of users
+	CHARACTER*80 BULLNEWS_FILE /'BULLNEWS.DAT'/	! Stores news group data
+C
+C  THE FOLLOWING IS THE DIRECTORY THAT IS USED TO STORE LOCAL NEWS GROUPS,
+C  I.E. NEWS GROUPS THAT ARE COPIED FROM THE NEWS SERVER AND SAVED LOCALLY.
+C  BULLETIN WILL CREATE SUBDIRECTORIES IN THIS DIRECTORY AND THE FILES WILL
+C  BE STORED IN THOSE SUBDIRECTORIES.
+C
+	CHARACTER*80 NEWS_DIRECTORY /'BULL_DIR:'/
diff --git a/decus/vmslt98a/bulletin/bullfolder.inc b/decus/vmslt98a/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..b3d94c80a06497cda925568659d1cc32f0fe7e7e
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullfolder.inc
@@ -0,0 +1,84 @@
+!
+!  The following 2 parameters can be modified if desired before compilation.
+!
+	PARAMETER BBEXPIRE_LIMIT = 30	! Maxmimum time limit in days that
+					! BBOARDS can be set to.
+	PARAMETER BBOARD_UPDATE = 15	! Number of minutes between checks
+					! for new BBOARD mail. (Note: Check
+					! only occurs via BULLETIN/LOGIN.
+					! Check is forced via BULLETIN/BBOARD).
+					! NOT APPLICABLE IF BULLCP IS RUNNING.
+	PARAMETER ADDID = .TRUE.	! Allows users who are not in the
+					! rights data base to be added
+					! according to uic number.
+
+	PARAMETER FOLDER_FMT = '(A44,A4,A8,A12,A80,A12,3A4,A8,10A4)'
+	PARAMETER FOLDER_RECORD = 220	! Must be multiple of 4
+
+	COMMON /BULL_FOLDER/ FOLDER,FOLDER_NUMBER,FOLDER_CREATED_DATE,
+     &		FOLDER_OWNER,
+     &		FOLDER_DESCRIP,FOLDER_BBOARD,FOLDER_BBEXPIRE,
+     &		USERB,GROUPB,ACCOUNTB,
+     &		F_NBULL,F_NEWEST_BTIM,FOLDER_FLAG,F_EXPIRE_LIMIT,
+     &		F_NEWEST_NOSYS_BTIM,F_START,F_COUNT,F_LAST,
+     &		FOLDER_FILE,FOLDER_SET,FOLDER_NAME
+	INTEGER F_NEWEST_BTIM(2)
+	INTEGER F_NEWEST_NOSYS_BTIM(2)
+	LOGICAL FOLDER_SET
+	DATA FOLDER_SET /.FALSE./, FOLDER/'GENERAL'/
+	CHARACTER FOLDER_OWNER*12,FOLDER*44,ACCOUNTB*8,FOLDER_NAME*80
+	CHARACTER FOLDER_FILE*80,FOLDER_DESCRIP*80,FOLDER_BBOARD*12
+	CHARACTER FOLDER_CREATED_DATE*8
+
+	CHARACTER*(FOLDER_RECORD) FOLDER_COM
+	EQUIVALENCE (FOLDER,FOLDER_COM)
+
+	COMMON /BULL_FOLDER1/ FOLDER1,FOLDER1_NUMBER,FOLDER1_CREATED_DATE,
+     &		FOLDER1_OWNER,
+     &		FOLDER1_DESCRIP,FOLDER1_BBOARD,FOLDER1_BBEXPIRE,
+     &		USERB1,GROUPB1,ACCOUNTB1,
+     &		F1_NBULL,F1_NEWEST_BTIM,FOLDER1_FLAG,F1_EXPIRE_LIMIT,
+     &		F1_NEWEST_NOSYS_BTIM,F1_START,F1_COUNT,F1_LAST,
+     &		FOLDER1_FILE,FOLDER1_SET,FOLDER1_NAME
+	CHARACTER FOLDER1_OWNER*12,FOLDER1*44,ACCOUNTB1*8,FOLDER1_NAME*80
+	CHARACTER FOLDER1_FILE*80,FOLDER1_DESCRIP*80,FOLDER1_BBOARD*12
+	CHARACTER FOLDER1_CREATED_DATE*8
+	INTEGER F1_NEWEST_BTIM(2)
+	INTEGER F1_NEWEST_NOSYS_BTIM(2)
+
+	CHARACTER*(FOLDER_RECORD) FOLDER1_COM
+	EQUIVALENCE (FOLDER1,FOLDER1_COM)
+
+	PARAMETER NEWS_FOLDER_FMT = '(A44,A4,2A8,A36,11A4)'
+	PARAMETER NEWS_FOLDER_RECORD = 144	! Must be multiple of 4
+
+	COMMON /NEWS_FOLDER/ NEWS_FOLDER,NEWS_FOLDER_NUMBER,
+     &		NEWS_F_CREATED_DATE,NEWS_F_EXPIRED_DATE,
+     &		NEWS_FOLDER_DESCRIP,NEWS_F_START,NEWS_F_COUNT,
+     &		NEWS_F_NBULL,NEWS_F_NEWEST_BTIM,NEWS_F_LAST,
+     &		NEWS_F_FLAG,NEWS_F_EXPIRE,NEWS_F_FIRST,
+     &		NEWS_F_EXPIRE_LIMIT,NEWS_F_END 
+	INTEGER NEWS_F_NEWEST_BTIM(2)
+	CHARACTER NEWS_FOLDER*44
+	CHARACTER NEWS_FOLDER_DESCRIP*36
+	CHARACTER*8 NEWS_F_CREATED_DATE,NEWS_F_EXPIRED_DATE
+
+	CHARACTER*(NEWS_FOLDER_RECORD) NEWS_FOLDER_COM
+	EQUIVALENCE (NEWS_FOLDER,NEWS_FOLDER_COM)
+
+        COMMON /NEWS_FOLDER_DEFAULT/ NEWS_FLAG_DEFAULT,
+     &	        NEWS_EXPIRE_DEFAULT,NEWS_EXPIRE_LIMIT_DEFAULT
+
+	COMMON /NEWS_FOLDER1/ NEWS_FOLDER1,NEWS_FOLDER1_NUMBER,
+     &		NEWS_F1_CREATED_DATE,NEWS_F1_EXPIRED_DATE,
+     &		NEWS_FOLDER1_DESCRIP,NEWS_F1_START,NEWS_F1_COUNT,
+     &		NEWS_F1_NBULL,NEWS_F1_NEWEST_BTIM,NEWS_F1_LAST,
+     &		NEWS_F1_FLAG,NEWS_F1_EXPIRE,NEWS_F1_FIRST,
+     &	        NEWS_F1_EXPIRE_LIMIT,NEWS_F1_END
+	INTEGER NEWS_F1_NEWEST_BTIM(2)
+	CHARACTER NEWS_FOLDER1*44
+	CHARACTER NEWS_FOLDER1_DESCRIP*36
+	CHARACTER*8 NEWS_F1_CREATED_DATE,NEWS_F1_EXPIRED_DATE
+
+	CHARACTER*(NEWS_FOLDER_RECORD) NEWS_FOLDER1_COM
+	EQUIVALENCE (NEWS_FOLDER1,NEWS_FOLDER1_COM)
diff --git a/decus/vmslt98a/bulletin/bullmain.cld b/decus/vmslt98a/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..bb3a4b5c7a988fd11c5c67a8b99fe2792c2177b2
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullmain.cld
@@ -0,0 +1,34 @@
+	MODULE BULLETIN_MAINCOMMANDS
+	DEFINE VERB BULLETIN
+		PARAMETER P1, LABEL=SELECT_FOLDER
+		QUALIFIER ALL
+		QUALIFIER BBOARD
+		QUALIFIER BULLCP
+		QUALIFIER CLEANUP, LABEL=CLEANUP, VALUE(REQUIRED)
+		QUALIFIER EDIT
+		QUALIFIER KEYPAD, DEFAULT
+		QUALIFIER LIBRARY, VALUE(REQUIRED)
+		QUALIFIER LOGIN
+		QUALIFIER MARKED
+		QUALIFIER PAGE, DEFAULT
+		QUALIFIER PGFLQUOTA, VALUE(TYPE=$NUMBER, REQUIRED)
+		QUALIFIER READNEW
+		QUALIFIER REVERSE
+!
+! The following line causes a line to be outputted separating system notices.
+! The line consists of a line of all "-"s, i.e.:
+!--------------------------------------------------------------------------
+! If you want a different character to be used, simply put in the desired one
+! in the following line.  If you want to disable the feature, remove the
+! DEFAULT at the end of the line.  (Don't remove the whole line!)
+!
+		QUALIFIER SEEN
+		QUALIFIER SEPARATE, VALUE(DEFAULT="-"), DEFAULT
+		QUALIFIER STARTUP
+		QUALIFIER STOP
+		QUALIFIER SYSTEM, VALUE(TYPE=$NUMBER, DEFAULT="7")
+		QUALIFIER UNSEEN
+		QUALIFIER UNMARKED
+		QUALIFIER WIDTH, VALUE(TYPE=$NUMBER, REQUIRED)
+		QUALIFIER WSEXTENT, VALUE(TYPE=$NUMBER, REQUIRED)
+		DISALLOW (WSEXTENT OR PGFLQUOTA) AND NOT STARTUP
diff --git a/decus/vmslt98a/bulletin/bullnews.inc b/decus/vmslt98a/bulletin/bullnews.inc
new file mode 100755
index 0000000000000000000000000000000000000000..fcbc81f4e3370155961774efc113178be317b39f
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullnews.inc
@@ -0,0 +1,7 @@
+	COMMON /NEWS_DEFAULTS/ ORGANIZATION,MAILER
+
+	CHARACTER*132 ORGANIZATION
+	DATA ORGANIZATION /'MIT PLASMA FUSION CENTER'/
+
+	CHARACTER*12 MAILER
+	DATA MAILER /'IN%'/
diff --git a/decus/vmslt98a/bulletin/bullstart.com b/decus/vmslt98a/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..ed1779cc0191d92a6e378bbb27c5c82fd163428d
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bullstart.com
@@ -0,0 +1,6 @@
+$ RUN SYS$SYSTEM:INSTALL
+BULL_DIR:BULLETIN/SHAR/OPEN/HEAD/-
+PRIV=(OPER,SYSPRV,CMKRNL,WORLD,DETACH,PRMMBX,SYSNAM)
+/EXIT
+$ BULL*ETIN :== $BULL_DIR:BULLETIN
+$ BULLETIN/STARTUP
diff --git a/decus/vmslt98a/bulletin/bulluser.inc b/decus/vmslt98a/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..5760e9235c2b5c12dbb4e64c63708fce310c3073
--- /dev/null
+++ b/decus/vmslt98a/bulletin/bulluser.inc
@@ -0,0 +1,53 @@
+!
+! The parameter FOLDER_MAX should be changed to increase the maximum number
+! of folders available.  Due to storage via longwords, the maximum number
+! available is always a multiple of 32.  Thus, it will probably make sense
+! to specify a multiple of 32 for FOLDER_MAX, as that it what really will be
+! the capacity.  Note that the default general folder counts as a folder also,
+! so that if you specify 64, you will be able to create 63 folders on your own.
+!
+	PARAMETER FOLDER_MAX = 96
+	PARAMETER FLONG = (FOLDER_MAX + 31)/ 32
+
+	PARAMETER USER_RECORD_LENGTH = 28 + FLONG*16
+	PARAMETER USER_FMT = '(A12,<4+FLONG*4>A4)'
+	PARAMETER USER_HEADER_KEY = '            '
+
+	COMMON /HEADER_INFO/ TEMP_USER,BBOARD_BTIM,NEWEST_BTIM,USERPRIV
+	COMMON /HEADER_INFO/ SET_FLAG_DEF,BRIEF_FLAG_DEF
+	COMMON /HEADER_INFO/ NOTIFY_FLAG_DEF
+	CHARACTER TEMP_USER*12
+	DIMENSION BBOARD_BTIM(2),NEWEST_BTIM(2),USERPRIV(FLONG)
+	DIMENSION SET_FLAG_DEF(FLONG),BRIEF_FLAG_DEF(FLONG)
+	DIMENSION NOTIFY_FLAG_DEF(FLONG)
+
+	COMMON /BULL_USER/ USERNAME,LOGIN_BTIM,READ_BTIM,
+     &		NEW_FLAG,SET_FLAG,BRIEF_FLAG,NOTIFY_FLAG
+	CHARACTER*12 USERNAME
+	DIMENSION LOGIN_BTIM(2),READ_BTIM(2)
+	DIMENSION NEW_FLAG(FLONG)   ! Used to indicate new message in folder
+				    ! Now NEW_FLAG(2) contains SET GENERIC days
+	DIMENSION SET_FLAG(FLONG)   ! Bit set indicates READNEW set for folder
+	DIMENSION BRIEF_FLAG(FLONG) ! Bit set indicates READNEW/BRIEF set
+	DIMENSION NOTIFY_FLAG(FLONG)! Bit set indicates to broadcast
+				    ! notification when new bulletin is added.
+
+	CHARACTER*(USER_RECORD_LENGTH) USER_ENTRY,USER_HEADER
+	EQUIVALENCE (USER_ENTRY,USERNAME)
+	EQUIVALENCE (USER_HEADER,TEMP_USER)
+
+	COMMON /FOLDER_TIMES/ LAST_READ_BTIM(2,0:FOLDER_MAX)
+	   ! Must start with 0 to store info for folder specified with ::
+	COMMON /SYS_FOLDER_TIMES/ LAST_SYS_BTIM(2,FOLDER_MAX)
+	   ! Last read times for each folder as stored in BULL_DIR:BULLINF.DAT
+	COMMON /NEWS_TIMES/ LAST_NEWS_READ(2,FOLDER_MAX)
+	INTEGER*2 LAST_NEWS_READ2(4,FOLDER_MAX)
+	EQUIVALENCE (LAST_NEWS_READ2(1,1),LAST_NEWS_READ(1,1))
+	   ! Last read times for each folder as stored in BULL_DIR:BULLINF.DAT
+
+	COMMON /INF_REC/ INF_REC(2,FOLDER_MAX)
+	INTEGER*2 INF_REC2(4,FOLDER_MAX)
+	EQUIVALENCE (INF_REC2(1,1), INF_REC(1,1))
+
+	COMMON /NEW_MESSAGES/ NEW_MSG
+	DIMENSION NEW_MSG(FLONG)   ! Flag showing new messages detected
diff --git a/decus/vmslt98a/bulletin/changes.txt b/decus/vmslt98a/bulletin/changes.txt
new file mode 100755
index 0000000000000000000000000000000000000000..366fa0091c250917bcd10688760e9be65e9d0804
--- /dev/null
+++ b/decus/vmslt98a/bulletin/changes.txt
@@ -0,0 +1,648 @@
+V 2.24
+
+When replying to a message in a news group that has been crossposted, give the
+user  the  option  of  just  posting  the reply to the news group in which the
+message is being read rather than  all  the  news  groups  in  the  crosspost.
+11/20/95
+
+Messages added to folders and stored news groups are now marked as being  read
+so that the person does not see them when doing a READ/NEW.  11/20/95
+
+Removed INCLUDE command and replaced it with the THREAD command.    This
+allows  you  to  save  and  easily  read new messages in threads via the
+READ/THREADS command.  11/13/95
+
+V 2.23
+
+Update newest read message when switching folders.  Previously this was done
+only when you exited BULLETIN, which would cause problems if you ran BULLETIN
+simultaneously from two different logins.  9/12/95
+
+Added /LIMIT to EXCLUDE and also the SET EXLIMIT command.   These  allow
+excludes to be specified so that they expire after a specified amount of
+days.  The SHOW EXCLUDE now will show the last time a message was found 
+that matched the exclude.  8/16/95
+
+Added /GROUP qualifier to DIRECTORY command to allow  specifying  groups
+to search using wild cards names.  8/3/95
+
+Added /GROUP qualifier to SEARCH command to allow specifying  groups  to
+search using wild cards names.  6/20/95
+
+V 2.22
+
+Added SHOW EXCLUDE and INCLUDE commands.  5/17/95
+
+Fixed bugs relating to messages with an expiration year past 1999.  5/17/95
+
+Fixed EXCLUDE/FROM as it did not work.   Also  fixed  EXCLUDE/DISABLE/ALL  and
+INCLUDE/DISABLE/ALL, as in some cases they would not work.3/31/95 
+
+V 2.21
+
+Modified the file format for stored news group to reduce disk space usage.
+11/29/94
+
+Added SET LIBRARY command and also /LIBRARY qualifier on the command line to
+allow switching between different directories which contain different sets of
+folders.  11/29/94
+
+Added /HEADER to POST when posting to news groups to allow adding headers to
+the message.  11/9/94
+
+Added /CANCEL to PRINT command which cancels previous print commands.
+10/28/94
+
+V 2.20
+
+Added /FOLLOWUP to the POST command.  10/12/94
+
+The FILE command no longer requires a file name, but will create a file
+name from the folder's name.  5/25/94
+
+Allow logical names to be specified in POST/GROUP.  5/12/94
+
+Added SET FILE_DIRECTORY command.  5/12/94
+
+Added /PERMANENT and /DEFAULT qualifiers to NEWS command.  4/28/94
+
+Added SET SUBSCRIBE command to allow setting default or permanent news groups. 
+4/26/94
+
+Added code to mail rejected posting for a stored news group to poster.  4/6/94
+
+Optimized newsgroup list upgrade to reduce  disk  I/O  which  greatly  reduces
+elapsed time for slow or fragmented disks.  4/5/94
+
+Modified /EDIT so EDT error no longer shows "no file found" message.  4/5/94
+
+Added SET NAME command to copy settings, used if username is changed.  3/28/94
+
+Modified SEARCH command to avoid updating new message counter (in order to be
+able to follow a thread and still use READ/NEW later).  3/26/94
+
+Added /INDENT=string to allow different indentation string.  3/12/94
+
+Added ability to allow BULLCP to gateway for NEWS access via TCP (for MULTINET
+only).  2/24/94
+
+Fix FROM header for news groups messages that have an address which continues
+on a 2nd line.  12/17/93
+
+V 2.19
+
+Add /MATCH qualifier to SEARCH command, and allow more than 1 string to be
+specified.  12/2/93
+
+Fixed the qualifer /CC when posting or resonding to messages.  It was supposed
+to be able to send to more than one user, but actually was sending to only the
+first user specified.  7/17/93
+
+Fixed alpha related problems.  7/16/93
+
+Fixed problem with responding to addresses of form: name <address>.  7/2/93
+
+Fixed shutdown bugs.  6/6/93
+
+Fixed /PRINT and /EXTRACT in DIRECTORY when used with a remote news group.
+5/29/93
+
+System messages which have longer lines than the terminal page width will have
+their text left justified rather than simply wrapped.  5/28/93
+
+Added SET [NO]EXCLUDE command to be  able  to  ignore  any  excludes  or
+includes that have been specified for that folder.  5/20/93
+
+V 2.18
+
+Added /FULL to EXCLUDE  and  INCLUDE  command  to  make  it  affect  all
+commands, such as directory listings.  5/13/93
+
+Fixed bug which displayed wrong foldername for notification broadcasts for
+messages added to bboard folders with digest set.  5/13/93
+
+Fixed bug which caused FOR003.DAT files to appear in DECNET directory due to
+BBOARD folder which has digest set.  5/10/93
+
+Fixed problem with inserting correct time when posting to news group.  5/5/93
+
+Fixed problem with BULL_DIR_LIST usage.  5/5/93
+
+Fixed shutdown problems.  5/3/93
+
+Fixed new executable message.  5/3/93
+
+Fixed bugs which caused FOR00x.DAT files to appear in DECNET directory during
+access from remote nodes.  4/29/93
+
+V 2.17
+
+Modified to work for ALPHA cpus.  4/5/93
+
+Speeded up DIRECTORY listing.  3/18/93
+
+Fixed FORWARD command from truncating subject lengths > 64.  3/18/93
+
+V 2.16
+
+Add code which causes nodename of remote folders to automatically be updated
+when the bulletin data files of the node containing the remote folders are
+moved to a different node.  3/12/93
+
+Fix incorrect display of NEWS/SUBSCRIBE/COUNT.  3/6/93
+
+In batch mode, paging is now automatically turned off and page width set to 80.
+3/5/93
+
+Fixed problem with shutdown messages not being deleted.  3/4/93
+
+V 2.15
+
+Code that converts data files if FOLDER_MAX is increased did not work.  2/27/93
+
+NEWS/SUBS now shows last read message.  INDEX now shows listing similar to
+DIR/FOLDER and NEWS. 2/27/93
+
+A user can make /HEADER be made the default for a folder or news group by adding
+a line to the user's customization file.  (See HELP custom) 2/21/93
+
+Personal names which are set in VMS MAIL are now automatically added to the from
+address when posting to news groups.  2/15/93
+
+Fixed bug which caused only partial storage of specified local news groups.
+2/5/93
+
+Fixed bug that caused privilege error and crash to occur after a non-privileged
+user posted a message to a folder which had an associated mailing list.  2/5/93
+
+V 2.14
+
+Added SET ANONYMOUS command so that all messages added to a folder will have
+the username ANONYMOUS rather than the actual username.  2/1/93
+
+Added /EXTRACT qualifie to DIRECTORY command.  1/31/93
+
+Added notification of new executable and possible new features.  1/26/93
+
+Dump log files are now created with acl for folder owner to be able to delete
+it.  1/26/93
+
+V 2.13
+
+Fixed bug in BBOARD code that corrupts file length.  1/15/93
+
+Fixed notification messages that showed wrong folder name.  1/15/93
+
+Added /[NO]HEADER and /ROTATE to NEXT (help said they were there, but they
+weren't).  1/15/93
+
+Added RESET command.  1/9/93
+
+Fixed bug in posting to stored news group by non-privileged users.  12/28/92
+
+V 2.12
+
+Fixed SET ACCESS /ALL which broke due to changes in V 2.11.  12/28/92
+
+Fixed problem with reply posting to stored news group not posting to proper
+group.  12/28/92
+
+Added code to allow setting access to news group or class of news groups.
+Added /PRIVATE switch to SET NEWS.  Added /CLASS to SET ACCESS.  12/26/92
+
+Fixed bug in code that does copying from news group to folder.  12/26/92
+
+Added INCLUDE and EXCLUDE commands which allow avoiding reading messages based
+on subject and address headers.  12/15/92
+
+Fixed bug which caused folder corruption.  12/15/92
+
+V 2.11
+
+Added SET NEWS command.  Used for setting a news group or a class of news
+groups to be stored on disk for quicker access by users (rather than being 
+read by users directly from the server).  Can also disable access to a group. 
+Users can set NOTIFY on stored groups.  11/5/92
+                                       
+NEWS command now by default shows only groups which are active.  Can show all
+groups with /ALL command.  /STORED and /COUNT are new qualifiers.  11/5/92
+
+Stored news groups are stored with data compression.  Normal folders can also be
+stored that way if set with the SET COMPRESS command.  11/5/92
+
+INDEX command modified to make it more useful.  /NEW is now the default, and now
+only shows folders or groups that have new messages.  /SET added to show only
+folders which have READNEW, SHOWNEW, or BRIEF set, and /SET is the default.
+11/5/92
+
+Fixed bug with BROADCAST routines which could cause BULLCP to go into MWAST
+state.  11/5/92
+
+Modified code which adds BBOARD messages to speed it up when multiple messages
+are being added.  11/5/92
+                                                 
+Folder names can now be up to 44 letters long.  11/5/92
+
+BULL_BBOARD_UPDATE and BULL_NEWS_UPDATE are now continuously translated by
+BULLCP so that they can be changed dynamically.  11/5/92
+
+BULLCP now is created with reasonable working quotas rather than PQL_ defaults
+which are usually way too low.  11/5/92
+
+Changed all variables to be long word multiples in order to be more ALPHA
+compliant (and maybe faster because of it?).  11/5/92
+
+/ROTATE added for read commands to allow reading messages encoded in ROT-13
+coding.  This is used by some news groups to display messages which could be
+taken as being offensive (i.e. rec.humor.funny).  11/5/92
+
+Fixed many minor bugs that no one mentioned, so I won't either.  11/5/92
+
+Fixed ADD/BROADCAST/EDIT not working with TPU.  8/13/92
+
+V 2.10
+
+Allow non-digest messages to be added to a folder which has DIGEST set.  8/6/92
+
+Added ADD_ONLY attribute.  If a mailing address is present, when messages are
+added to a folder, they will also be mailed to the address.  Users are
+prevented from using the POST command.  Instead, the ADD command will be used
+if the POST command is entered.  One use for this is a local board which is
+also distributed to non-local users.  8/1/92
+
+Added POST_ONLY attribute  This causes the ADD command to mail messages to the
+mailing address if it is present, rather than add it to the folder.  8/1/92
+
+Fixed several shutdown bugs.  7/23/92
+
+Fixed PMDF broken by V2.09.  6/16/92
+
+Added system logical name BULL_CUSTOM.  It is equated to a hex number string.  
+Bit 0 set = need privileges to create folder, 1 set = captive account can
+write files, 2 set = captive account can use editor.  5/25/92
+
+V 2.09
+
+Allow having more than one database by redefining BULL_DIR.  However, only 
+directories that are defined in the list of equivalence names pointed to by
+the system logical name BULL_DIR_LIST are allowed.  See AAREADME.TXT
+for more info.  5/10/92
+
+GENERAL folder can now be renamed or modified (not deleted).  4/22/92
+
+/FROM, /NOREPLIES, & /NEGATED added to SEARCH and DIRECTORY commands.  3/18/92
+
+Mail routines now use MAIL$ calls for outgoing mail for faster execution.  
+3/15/92
+
+Changing keypad definitions using initialization file now possible.  3/12/92
+
+Subscribed news groups are now listed in alphabetical order.  3/7/92
+
+V 2.08
+
+Fixed bug which caused missing news groups. See NEWS.TXT for info.  2/25/92
+
+Allow setting local protection on remote folders.  12/12/91
+
+Fixed bug with creation of folder files.  If they were deleted after the folder
+was created, the files that would be created by BULLETIN to replace them (when
+the folder is selected) would be created with the wrong protection.  12/12/91
+
+Fix problem with MULTINET V3.0 and DECNET/NEWS gateway feature.  BULLCP will
+hang without this fix if there is an attempt to read news via it.  12/9/91
+
+Fix bug that causes incorrect time on news postings after the first post. 
+Display time when reading news messages in local rather than GMT time.  12/8/91
+
+Add 30 second timeout for connecting to nameserver for news.  Can be increased
+up to 99 seconds via defining BULL_NEWS_TIMER.  12/3/91
+
+Allow list of numbers when specifying message numbers for PRINT and FILE
+commands.  11/27/91
+
+Fixed bugs in BBOARD code:  Messages with lines > 255 characters would not be
+included.  Subject line not correctly extracted if next line was simply a
+To:. (relink PMDF driver if using PMDF for patch to take affect).  11/27/91
+
+V 2.07
+
+NEWS listing now shows the status of the news group, i.e. active, inactive,
+moderated, or renamed.  10/23/91
+
+Fixed PRINT command so that if a print qualifier (i.e. /QUEUE) is specified,
+it will cause any pending print jobs to be printed if the qualifier for the
+pending jobs is different.  10/23/91
+
+Added /NOSIGNATURE qualifier for POST & RESPOND commands.  10/21/91
+
+Fixed error in POST & RESPOND command.  If a file was specified on the command
+line, and /EDIT was specified, the file would be sent even if the user quit out
+of the edit, rather than exitting (i.e. outputting a file).  10/21/91
+
+Fixed REPLY option in READNEW, as it was possible for users with only read
+access to a folder to be able to add REPLY messages.  10/10/91
+
+Add REPLY option to READNEW feature when reading messages.  Also, really fix
+the REPLY command, as mentioned in V2.06.  8/11/91
+
+V 2.06
+
+Added code to keep track of which messages have been read a per message basis. 
+Added SEEN & UNSEEN commands.  Added /SEEN, /UNSEEN, and /UNMARKED to
+DIRECTORY, INDEX, READ, and SELECT commands.  Modified directory listing to
+indicate which messages have been SEEN.  7/31/91 
+
+Added /NOW to PRINT command.  Messages no longer have to be printed one message
+at a time.  It now works identical to VMS MAIL.  7/31/91
+
+Added code to NEWS users when new groups have been created.  User will be
+alerted when selecting a news group that new groups are present, and will be
+instructed to type NEWS/NEWGROUP in order to see them.  7/31/91
+
+Added /PRINT to DIRECTORY command to allow printing of messages which are found
+by using the DIRECTORY command.  7/31/91
+
+Modified directory listing display so that the first and last message in the
+folder are now displayed at the top.  Fixed bug which truncated very large news
+group names.  7/31/91
+
+Added FIRST command to read first message found in folder.  7/31/91
+
+Modified REPLY command for folders associated with mailing lists, so that the
+reply message to the mailing list rather than adding a local message.  7/31/91
+
+Modified code to correctly store subject headers from BBOARD mail which are
+more than one line long.  Previously, the subject would be truncated.  6/18/91
+
+V 2.05
+
+The MARK code was modified to work with NEWS folders.  6/3/91
+
+Added /FOLDER=(folder,[...]) to the SEARCH command to allow searching more than
+one folder at a time.  6/13/91
+
+NEWS/SUBSCRIBED listing was fixed.  If the list could not fit on a single page,
+a folder was skipped when the next page was shown.  6/3/91
+
+INDEX was fixed.  If it was used with the qualifiers /NEW or /MARK, and the
+directory listing of a folder was displayed, and then RETURN is entered to 
+skip to the next folder, the directory display of the next folder would be
+incorrect.  6/3/91 
+
+Fixed broadcast bug.  If a message was added with /BROADCAST to a remote folder
+from a node in a cluster which was not the node that BULLCP was running on. 
+The broadcast would appear twice on the cluster.  5/24/91
+
+Added code to alert user if message too large to be fully broadcasted.  5/24/91
+
+Added code to avoid erroneous notifications of new messages for an empty NEWS
+group.  Unlike a similar fix in V2.03 which was due to a bug, this fix may not
+affect all sites, as it depends on the behavior of the server.  5/22/91 
+
+Fixed NEWS to FOLDER feed.  A recent change broke it.  5/22/91
+
+Added /EDIT qualifier for MAIL.  5/20/91
+
+Added /HEADER qualifier for LAST, BACK, and CURRENT commands.  5/19/91
+
+Added TWG (Wollongong) interface for NEWS.  5/18/91
+
+Fixed bug which truncated subject headers of messages created when using REPLY
+and RESPOND to messages which have long subject lines.  5/12/91
+
+V2.04
+
+Added ALWAYS attribute for folders.  Any SYSTEM messages in a folder in which
+ALWAYS has been set will be displayed every time a user logs in, rather than
+just once.  Also, non-SYSTEM messages will be displayed continuously (via
+whatever mode is set, i.e. READNEW, SHOWNEW, or BRIEF) until it is actually
+read.  4/29/91 
+
+Added capability of controlling the time between updates for BBOARD and NEWS in
+BULLCP by defining the logical names BULL_BBOARD_UPDATE or BULL_NEWS_UPDATE to
+the number of minutes of desired time in minutes. 4/27/91
+
+Added /GROUPS= qualifier to all commands which post to NEWS groups. 4/26/91
+
+Fixed bug which prevented SET SHOWNEW or READNEW from working with subscribed
+news group folders. 4/25/91
+
+V2.03
+
+Added /FOLDER to SHOW USER in order to show the latest message that a user
+has read in the specified folder.  Also added /SINCE and /START (the former
+for real folders, the latter for news groups).  4/11/91
+
+Fixed logic so that defining BULL_NEWS_ORGANIZATION will override the
+definition defined in BULLNEWS.INC.  4/10/91
+
+Fixed SEARCH command, as it broke in V2.02 when /EDIT was added to read
+message commands.  There is a missing QUALIFIER EDIT in BULLCOM.CLD for the
+SEARCH verb.  /EDIT now works with SEARCH.  4/9/91
+
+Fixed bug in BULLCP which prevented the DECNET/INTERNET NEWS gateway software
+from working with UCX.  4/9/91 
+
+Fixed bug caused by V2.00 which caused incorrect listing of message during
+BULL/LOGIN for remote folders.  4/3/91
+
+Fixed bugs which caused erroneous new message notifications for subscribed
+NEWS groups that were empty.	3/27/91
+
+V 2.02
+
+Include BBOARD support for MX (courtesy of goathunter@wkuvx1.bitnet).
+
+Changed BBOARD algorithm so that it is now possible to have only one real
+BBOARD account, and have all the others be VMS MAIL forwarding entries.
+See HELP SET BBOARD MORE_INFO for more info (it's been updated).
+
+Added hook to allow postings from BULLETIN to a LISTSERV mailing list to use
+the BBOARD account from it was subscribed to.  See HELP SET BBOARD LISTSERV.
+
+Fixed many bugs in POST, REPLY, and RESPOND.
+
+Fixed /ALL for COPY, PRINT, and EXTRACT when using NEWS groups.
+
+Included RMS optimizer procedure for indexed files to optimize BULLNEWS.DAT
+to speed up NEWS updates.  Can be used on other files (in particular
+BULLINF.DAT) in order to save space.
+
+Add /EDIT to BACK, NEXT, LAST, and when entering message number.
+
+Modify ADD/REPLY command to local (non-NEWS) folders so if there are new
+messages present, it doesn't reset the newest message count.  Previously,
+adding a message would reset the user's last read message date to that message
+in order to avoid notifying the user of new messages due to the user's own
+message. 
+
+Fixed code so that when reading new messages, and if READ/EDIT or DELETE/IMMED-
+IATE IS entered, a carriage return will read the next new message.  Previously
+the wrong message would be displayed.
+
+V 2.01
+
+Fixed many bugs associated with USENET NEWS reading feature.
+
+Added UCX interface for NEWS.
+
+Added signature file for POST and RESPOND messages.
+
+Added capability to specify file name for POST, REPLY, and RESPOND.
+
+Added the line "In a previous message, <message-owner> wrote:" to the
+beginning of a message when /EXTRACT is specified
+
+Added hook for network mail to run command procedure rather then using
+VMS MAIL.  BULL_MAILER can be defined to point to the procedure, and it
+is called with the username and subject as the parameters.
+
+V 2.00
+
+Added USENET NEWS reading feature.
+
+V 1.93
+
+Fixed bug which wouldn't allow a permanent message to be added by a
+non-privileged user in a remote folder (the folder had been setup to allow
+permanent messages from non-privileged users, of course). 
+
+Fixed bug which causes the DELETE command not to delete a SHUTDOWN message
+without the use of /IMMEDIATE.
+
+Fixed the algorithm which prevented duplicate notification of messages in
+remote folders on different nodes, as duplication was still possible.
+
+V 1.92
+
+Fixed bug which causes BULLCP to loop when trying to cleanup a folder which
+has more than 127 identifiers granted access to a folder.  Also correct
+SHOW FOLDER/FULL, which had a similar problem when trying to display the
+identifiers.
+
+Fix PMDF interface to recognize to recognize PMDF_PROTOCOL.
+
+V 1.91
+
+Disallow SPAWN command for CAPTIVE account.
+
+Fix MAIL command to correctly allow passing addresses with quotes, i.e.
+IN%"""MRL@NERUS.PFC.MIT.EDU""".
+
+V 1.90
+
+SET NOTIFY now works for remote folders.
+
+Avoid generating notification message due to SET NOTIFY flag if the message
+was broadcasted when added using ADD/BROADCAST.
+
+Bug in DIR/SINCE for remote folders fixed.  If no new messages were present,
+it would incorrectly show messages.
+
+Added /FF to EXTRACT command to seperate messages in the file with form feeds.
+
+Allow specifying CURRENT and LAST when specifying a range of messages for
+commands that accept a range, i.e. EXTRACT 1-CURRENT, CURRENT-LAST, etc.
+
+Open folder files with READONLY when not writing to them in order to avoid
+changing modification date, which results in unnecessary backups.
+
+Modify HELP so that it won't prompt for Subtopic is there is none.
+
+Prevent screen from being erased after exiting HELP.
+
+Fix bug which causes CREATE/NOTIFY to crash.
+
+SET NOTIFY/CLUSTER has been removed.  As of VMS V5.2, it is possible to obtain
+the list of users logged in to all nodes of a cluster, so this qualifier is no
+long necessary.  NOTE: You can delete all the BULL_DIR:*.NOTIFY files, as they
+are no longer used.
+
+BULLETIN now will use the editor specified by the SET EDITOR command within
+MAIL for editing messages.
+
+Typing BACK after typing a DIRECTORY command will now show the previous 
+DIRECTORY display entries rather than reading the previous message.
+
+Several bugs related to the MARK command were fixed.  Also the software has been
+optimized so that scanning for MARKed messages should take less time.
+
+/EXPIRATION added to DIRECTORY command to show expiration rather than creation
+date of messages.
+
+Any BULLETIN interactive command can be executed at DCL level by typing
+BULLETIN "command" or BULLETIN "command1;command2;etc.".
+
+The CHANGE command has been modified so a range of message can be specified,
+i.e. /NUMBER=1-10.  Also, the code incorrectly misinterpreted /TEXT as meaning
+to extract the old text message, whereas it should have meant that only the
+text was to be changed.  This prevented a user from specifying that only the
+text should be changed if that user didn't have editing enabled.  This has been
+fixed.  To eliminate confusing, the /TEXT qualifier on the ADD command has been
+removed (previously it was a synonym for /EXTRACT). 
+
+SHOW FOLDER/FULL display of access IDs was fixed to correctly display UICs.
+
+Removed security hole which occurs if you are using the old method of accessing
+a remote node via /NODES (it would have required looking a the sources to find,
+which one installer did and was worried about).  Because of this, if you use
+this old method (i.e. via BULLETIN.COM), the object BULLETIN must be installed
+in the NCP database pointing to the file BULLETIN.COM, i.e. the command
+"MCR NCP SET BULLETIN FILE directory:BULLETIN.COM NUMBER 0" must be executed
+during the system startup.
+
+Fixed bug in /LOGIN display when erasing page if terminal is hardcopy.  No
+page would be erased (of course), and the next line outputted would start where
+the previous line left off, rather than starting on a new line.
+
+Added BULLETIN/WIDTH=page_width for users who have BULLETIN/LOGIN in their
+login procedure before the terminal is known, and whose default page width is
+larger (i.e. 132) than what the terminals are (i.e. 80).
+
+Added BULLETIN/PGFLQUOTA and /WSEXTENT in order to set those quotas for the
+BULLCP process.
+
+Added ATTACH command.
+
+Modify SET STRIP so that it saves the date that the message was sent and
+leaves it at the to of the message.
+
+BULLETIN will search BBOARD message headers for a line that starts with
+"Expires:" or "X-Expires:", followed by a date (DD MMM YYYY or similar).  It if
+finds that line, it will use that date as the expiration date of the message. 
+
+Added /REPLY to SEARCH command.  Modified so that it's possible to abort out of
+a /SUBJECT or /REPLY search using CTRL-C (previous possible only if searching
+the text for a string.  Also, if you hit CTRL-C at the wrong time, BULLETIN
+would abort totally rather than just aborting the search). 
+
+Added /SEARCH= /SUBJ= and /REPLY to the DIRECTORY command.  Basically this is
+combining the DIRECTORY and SEARCH commands.
+
+Fixed design flaw which allowed the following to occur:  If a folder is a
+remote system folder, when BULLETIN/LOGIN was executed, the same messages might
+be displayed on both the local and remote nodes.  BULLETIN now will know that
+the user has seen the message on one node and will not display it if that user
+logs in on the other node.
+
+Optimized code which caused slow display of new messages when executing
+BULLETIN/LOGIN without /REVERSE for a remote folder.
+
+Added /PERMANENT to SET NOTIFY, SHOWNEW, BRIEF, and READNEW.  The affect is
+that users will not be allowed to change the setting.  The main intent here
+was to allow the removal ofthe permanent setting of SHOWNEW from the GENERAL
+folder.
+
+Fixed bug which would cause a SYSTEM message not to be shown if SET BRIEF was
+selected for that folder, and a non-SYSTEM message was also present.
+
+Added SET CONTINUOUS_BRIEF.  This causes the SET BRIEF setting to show that
+there are unread new messages every time BULLETIN/LOGIN is executed, rather
+than just the one time.  The BRIEF notification code has also been optimized
+so that it'll take less time to notify you of new messages.
+
+A major bug was fixed which was introduced in previous mods to speed up
+BULLETIN/LOGIN.  The effect is that no notifications will appear for certain
+folders via BULLETIN/LOGIN.  This would only happen if a folder was removed at
+some time.
diff --git a/decus/vmslt98a/bulletin/cmds.mai b/decus/vmslt98a/bulletin/cmds.mai
new file mode 100755
index 0000000000000000000000000000000000000000..804e43e75a08724e983452487e24fa87050266b6
--- /dev/null
+++ b/decus/vmslt98a/bulletin/cmds.mai
@@ -0,0 +1,22 @@
+The address for getting BULLETIN is BULLETIN@PFC.MIT.EDU.
+
+Valid commands are:
+	SEND ALL [SINCE time]	Sends all bulletin files.
+				If SINCE time specified, only files created
+				since that time will be sent.
+	SEND filename		Sends the specified file
+				(only one file per command).
+	DIR			Lists available files.
+	BUGS			Sends a list of the latest bug fixes.
+	HELP or INFO		Sends a brief description of BULLETIN.
+	SUBSCRIBE		Subscribes to mailing list for upgrade
+				notifications.
+	UNSUBSCRIBE		Unsubscribes from mailing list.
+
+Send those commands in either the text of the message, one command per line,
+or send a single command in the subject header.
+
+BULLETIN is also available via ANONYMOUS FTP from PFC.MIT.EDU, but the account
+is set at low priority, so I suggest using it during non-prime hours.
+
+								Mark
diff --git a/decus/vmslt98a/bulletin/copyright.txt b/decus/vmslt98a/bulletin/copyright.txt
new file mode 100755
index 0000000000000000000000000000000000000000..b6edd1b9bbf2a69adcdbbff41b17777c8b5a0989
--- /dev/null
+++ b/decus/vmslt98a/bulletin/copyright.txt
@@ -0,0 +1,29 @@
+"Bulletin" Z License
+
+This software is being provided to you, the LICENSEE, by the Massachusetts
+Institute of Technology (M.I.T.) under the following license.  By
+obtaining, using and/or copying this software, you agree that you have
+read, understood, and will comply with these terms and conditions:  
+
+Permission to use, copy, modify and distribute without fee  for  any  purpose,
+this  software and its documentation without fee or royalty is hereby granted,
+provided that you agree to comply with  the  following  copyright  notice  and
+statements,  including  the disclaimer, and that the same appear on ALL copies
+of the software and documentation, including modifications that you  make  for
+internal use or for distribution: 
+
+Copyright 1985 by the Massachusetts Institute of Technology.  All rights
+reserved.  
+
+THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS OR
+WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not limitation,
+M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE OR
+DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
+TRADEMARKS OR OTHER RIGHTS.   
+
+The name of the Massachusetts Institute of Technology or M.I.T. may NOT be
+used in advertising or publicity pertaining to distribution of the
+software.  Title to copyright in this software and any associated
+documentation shall at all times remain with M.I.T., and USER agrees to
+preserve same.  
diff --git a/decus/vmslt98a/bulletin/create.com b/decus/vmslt98a/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..9427f4fa7ad912e142ceab952d501494c8b3e982
--- /dev/null
+++ b/decus/vmslt98a/bulletin/create.com
@@ -0,0 +1,57 @@
+$ FQ = ""
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN FQ = "/SEPARATE_COMPILATION"
+$ IF F$GETSYI("VP_MASK") .NE. 0 THEN FQ = FQ + "/NOHPO"
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN0
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN1
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN2
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN3
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN4
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN5
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN6
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN7
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN8
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN9
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN10
+$ FORTRAN/NOWARN/EXTEND/CHECK=(NOBOUNDS,OVERFLOW,NOUNDERFLOW)'FQ' BULLETIN11
+$ IF F$GETSYI("HW_MODEL") .LE. 1023 THEN MAC ALLMACS
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN MAC ALLMACS_AXP
+$ SET COMMAND/OBJ BULLCOM
+$ SET COMMAND/OBJ BULLMAIN
+$ CCQ = ""
+$ IF F$GETSYI("HW_MODEL") .GT. 1023 THEN CCQ = "/STAN=VAX"
+$ ON WARNING THEN GOTO DUMMY
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .NES. "" THEN GOTO MULTI
+$ IF F$TRNLNM("TWG$TCP") .EQS. "" THEN GOTO MULTI
+$ DEFINE VAXC$INCLUDE TWG$TCP:[NETDIST.INCLUDE],-
+                      TWG$TCP:[NETDIST.INCLUDE.SYS],-
+                      TWG$TCP:[NETDIST.INCLUDE.VMS],-
+                      TWG$TCP:[NETDIST.INCLUDE.NETINET],-
+                      TWG$TCP:[NETDIST.INCLUDE.ARPA],-
+                      SYS$LIBRARY
+$ CC'CCQ' BULL_NEWS/DEFINE=(TWG=1)
+$ GOTO LINK
+$MULTI:
+$ IF F$TRNLNM("MULTINET_SOCKET_LIBRARY") .EQS. "" THEN GOTO UCX
+$ CC'CCQ' BULL_NEWS/DEFINE=(MULTINET=1)
+$ GOTO LINK
+$UCX:
+$ IF F$TRNLNM("UCX$DEVICE") .EQS. "" THEN GOTO CMU
+$ CC'CCQ' BULL_NEWS/DEFINE=(UCX=1)
+$ GOTO LINK
+$CMU:
+$ CC'CCQ' BULL_NEWS
+$ GOTO LINK
+$DUMMY:
+$ WRITE SYS$OUTPUT "There is no C compiler available for the NEWS software."
+$ WRITE SYS$OUTPUT "BULLETIN will be assembled without that feature."
+$ FORTRAN BULL_NEWSDUMMY
+$LINK:
+$ SET NOON
+$ IF F$SEARCH("BULL_DIR:READ_BOARD.COM") .NES. "" THEN-
+  DELETE BULL_DIR:READ_BOARD.COM;*
+$ IF F$SEARCH("BULL.OLB") .NES. "" THEN DELETE BULL.OLB;*
+$ IF F$SEARCH("BULL.OLB") .EQS. "" THEN LIBRARY/CREATE BULL
+$ LIBRARY BULL *.OBJ;
+$ DELETE *.OBJ;*
+$ @BULLETIN.LNK
diff --git a/decus/vmslt98a/bulletin/handout.txt b/decus/vmslt98a/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..5a1acd2568bdbb84c026c6f1a4994b5799554811
--- /dev/null
+++ b/decus/vmslt98a/bulletin/handout.txt
@@ -0,0 +1,268 @@
+               Introduction to BULLETIN on the Vax
+                                                  2/88 AW
+
+PUBLISHED BY THE DREW UNIVERSITY ACADEMIC COMPUTER CENTER. MAY BE
+COPIED WITH WRITING CREDIT GIVEN TO DREW UNIVERSITY.
+
+BULLETIN was written for the Public Domain by Mark London at MIT.
+
+     The BULLETIN utility permits a user to create messages for
+reading by other users.  Users may be notified upon logging on
+that new messages have been added, and what the topic of the
+messages are.  Actual reading of the messages is optional.  (See
+the command SET READNEW for info on automatic reading.)  Messages
+are automatically deleted when their expiration data has passed.
+     The program runs like VAX mail.  The different interest
+groups or BULLETIN boards are implemented in the form of
+'Folders', just like a filing cabinet.  A Folder contain various
+messages on the same general topic.  A message is a piece of text
+written by a user or staff person and added to a particular
+folder.  All users are not permitted to submit messages to all
+folders.
+
+     A message consists of an expiration date, a subject line
+and the text of the message.  BULLETIN will prompt the user for
+these things when a message is being added.
+
+     Several different folders are currently defined to
+BULLETIN.  The General Folders will be used by Computer Center
+Staff to post messages of general interest concerning the VAX to
+the user community.  If something is of an important nature, it
+will be posted in the General folder as a 'System' message.
+This is a special message type.  It will be displayed to each
+user  as they log in the first time after that message was
+posted.  This will be done automatically by BULLETIN on login.
+Once a particular system message has been displayed, it will not
+be displayed for that user on subsequent logins.
+
+Folders
+
+     Different folders have been created to contain messages on
+different topics.  Folders may be public, semi-private, or
+private.  The majority of the folders will be public.  However a
+few will be semi-private, which will mean that all users may
+read messages in the folder but not all will be able to post to
+it.  Currently, there are several folders defined:
+
+GENERAL -- system messages
+
+PUBLIC_ANNOUNCEMENTS -- Can be used by anyone to post messages
+of interest to the public
+
+On Beta:
+AIDE STATION -- Private folder for Computer Center Employees
+
+In addition on Alpha there are folders that receive electronic
+magazines, such as:
+NETMONTH --  The monthly magazine of BITNET information.
+RISKS -- Identifying the risks involved in using computers.
+INFOIBMPC -- Information about the IBM personal computers.
+INFOVAX -- Information on the Digital VAX.
+PROGRAMMING_JOURNALS-Includes MINIX, UNIX and C, Modula-2 and
+Prolog journals
+watch for new ones being added.
+
+Using BULLETIN
+
+     BULLETIN is invoked by type the command 'BULLETIN' (or BULL,
+for short) at the '$' prompt.  BULLETIN will display its prompt
+'BULLETIN>'. Help is available from DCL command level ($) or from
+within the BULLETIN program itself by typing the word 'HELP'.  To
+leave the BULLETIN program, type 'EXIT'.
+
+To see what is there
+
+     In order to see message and folders, on can use the
+'Directory' command. Upon entering BULLETIN, the user is place
+in the General folder.  If the user wishes to see which folders
+exist, the directory/folders command is used. for example:
+typing:
+
+     BULLETIN> directory/folders
+
+will make a display like:
+
+      Folder                       Owner
+     *GENERAL                      SYSTEM
+     *PUBLIC_ANNOUNCEMENTS         BBEYER
+      NETMONTH                     BITNET
+     *VAX_SIG                      BBEYER
+
+An asterisk (*) next to the folder name indicates you have unread
+messages in that folder.
+
+The command 'DIRECTORY/FOLDERS/DESCRIBE' would list all available
+folders, along with a brief description of each.
+
+     To switch from one folder to another folder, the user may
+execute the 'SELECT' command.  For example, the following
+command would show what a user would do to switch to the folder
+called PUBLIC_ANNOUNCEMENTS:
+
+BULLETIN> SELECT PUBLIC_ANNOUNCEMENTS
+
+and BULLETIN would respond:
+     Folder has been set to PUBLIC_ANNOUNCEMENTS
+
+     Now the user may get a list of the messages in this folder
+by issuing the directory command with no qualifiers.
+This command, for example:
+BULLETIN> DIRECTORY
+would have bulletin respond:
+
+ #     Description               From                  Date
+ 1     CHRISTMAS PARTY           oleksiak              26-JUN-88
+ 2     Learning about BULLETIN   oleksiak              26-JUN-87
+ 3     VAX MAIL                  LLLOYD                01-Jan-87
+
+     The command 'DIR/NEW' will list just unread messages.
+
+
+Reading messages
+
+     In order to read messages in a folder, the user may type
+the read command or he/she may simply type the number of the
+message he wishes to read.  The message numbers can be acquired
+by doing the 'DIRECTORY' command.  If the user hits a carriage
+return with no input whatsoever,  BULLETIN will type the first
+message in the folder, or if there are new messages present, it
+will type the first new message in the folder.
+
+     If a folder contains the above messages (as seen by the
+'Directory' command) then these messages can be read by:
+
+BULLETIN> READ
+and BULLETIN would respond:
+
+Message number:  1                       PUBLIC_ANNOUNCEMENTS
+Description: CHRISTMAS PARTY
+Date:  26-JUN-1988 8:08:40   Expires:  1-JAN-1989 08:08:40
+
+...Body of message.....
+
+     Should the user only wish to see message number 3, he can
+enter the 'READ' command with the message number as a parameter.
+for example:
+
+BULLETIN> READ 3
+
+     There are three other useful commands that can be used at
+the 'BULLETIN>' prompt when reading messages. These are:
+
+BACK - Read the message preceding the message currently being
+read.
+
+CURRENT - Start reading the current message at the top.  This is
+useful for someone who is reading a message and wishes to reread
+it from the beginning.
+
+NEXT - Start reading from the beginning of the next message.
+This is handy if the user is reading a very long message and
+wants to skip to the next one.
+
+Saving the interesting stuff.
+
+     If the user sees something which he/she wants a copy of,
+the extract command can be use to write an ASCII copy of the
+message into a file.  This command works on the current message
+being read.  It requires the name of the file into which to save
+the message.  If the file name is not given, the user will be
+prompted for it.  For example:
+
+BULLETIN>  Read 2
+
+********** Message on Screen ********
+
+A person could then type
+BULLETIN> extract
+file:  FV.TXT
+BULLETIN>
+
+BULLETIN has now saved the contents of message number 2 into the
+file name 'FV.txt'.
+     If the file to which the user is writing already exists,
+BULLETIN will append the message to the file.  The user can
+force BULLETIN to write a new file containing only the message
+being saved by using the '/new' qualifier in the 'extract'
+command.  These messages can then be sent to other users, or
+downloaded for use in Wordperfect.  (See "Mail on the Vax", or
+"Transferring a file between a PC and the VAX").
+
+This command may be useful if you wish to transfer the message to
+your PC, perhaps using a BITNET journal message as a reference in
+a paper. Once the file is saved, you can transfer it to a PC by
+following the instructions in the handout 'Transferring files
+from the PC to the VAX of from the VAX to a PC".
+
+Adding messages
+     A user may add a message to a folder by selecting the
+folder and then using the 'ADD' command.  This is provided that
+the user is adding the message to a public folder.  The user has
+the option of giving the 'ADD' command and typing a message using
+the VAX editor or uploading a message from your PC (see
+documentation), or add a message you have extracted from VAX
+mail.  BULLETIN will prompt for the expiration date and subject
+line.  It will then add the text of the file as the body of the
+message. To add a message that is stored in a file (from MAIL or
+from your PC, for example) type:
+
+          ADD filename
+
+If the user does not specify a file name, he/she will be
+prompted to enter the body of the message.  The user may also
+use the EDT text editor by issuing the command with the
+'/EDIT'option.
+
+For example:
+BULLETIN> sel PUBLIC_ANNOUNCEMENTS
+          folder has been set to PUBLIC_ANNOUNCEMENTS
+BULLETIN> ADD MESS.TXT
+
+IT IS 10-JUL-1988 12:41:06.15.  SPECIFY WHEN THE MESSAGE SHOULD
+EXPIRE:  ENTER ABsolute TIME:  <DD-MMM-YYYY]HH:MM:SS OR DELTA
+TIME: DDD HH:MM:SS
+
+A user then type the date of expiration and press the 'return'
+button.  The time input may be ignored. For example, typing:
+20-JUL-1988 or type "10" - for ten days in the future.
+
+BULLETIN responds:
+ENTER DESCRIPTION HEADER.  LIMIT HEADER TO 53 CHARACTERS.
+
+Now the user may enter the subject of the message.
+
+BULLETIN>
+
+The above session adds the text in the file 'mess.txt' as the
+next message in the PUBLIC_ANNOUNCEMENTS Folder.  The message
+will be deleted automatically on the 20th of July as requested
+by the user adding the message.
+
+Asking BULLETIN to notify you of new messages upon logging in.
+
+     If the user wishes to get notification on login when new
+messages are in a folder, he should use the 'READNEW' option.
+This command does not force the reader to reading new messages,
+only gives notification.  To do this, 'SELECT' each folder you
+are interested in and do a 'SET READNEW' command while set to
+that folder.
+
+Example:
+
+BULLETIN> Select PUBLIC_ANNOUNCEMENTS
+folder has been set to PUBLIC_ANNOUNCEMENTS
+BULLETIN> SET READNEW
+
+Alternately, you may type SET SHOWNEW. This will just display a
+message notifying you that there are new messages.
+
+Mailing a BULLETIN message
+
+     A user may directly mail another user a message found in the
+BULLETIN.  While reading the message that he/she desires to send,
+at the 'BULLETIN>' type 'MAIL'.  The Vax will then ask to whom
+you wish to send the information too.
+
+Check the BULLETIN DISCUSSION folder on ALPHA for new additions.
+If you have comments or questions about BULLETIN, leave them
+there.
diff --git a/decus/vmslt98a/bulletin/install.com b/decus/vmslt98a/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..34427ba06e29d10e305740acd87ab2de55b4678e
--- /dev/null
+++ b/decus/vmslt98a/bulletin/install.com
@@ -0,0 +1,25 @@
+$ IF F$TRN("BULL_DIR") .EQS. ""
+$ THEN
+$   WRITE SYS$OUTPUT "ERROR: BULL_DIR has not been defined yet."
+$   WRITE SYS$OUTPUT "Assign BULL_DIR as a logical name or modify this"
+$   WRITE SYS$OUTPUT "command procedure to point to the appropriate directory."
+$   EXIT
+$ ENDIF
+$ COPY BULLETIN.EXE BULL_DIR:
+$ RUN SYS$SYSTEM:INSTALL
+BULL_DIR:BULLETIN/DEL
+BULL_DIR:BULLETIN/SHAR/OPEN/HEAD/-
+PRIV=(OPER,SYSPRV,CMKRNL,WORLD,DETACH,PRMMBX,SYSNAM)
+/EXIT
+$!
+$! NOTE: BULLETIN requires a separate help library. If you do not wish
+$! the library to be placed in SYS$HELP, modify the following lines and
+$! define the logical name BULL_HELP to be the help library directory, i.e.
+$!	$ DEFINE/SYSTEM BULL_HELP SYSD$:[NEWDIRECTORY]
+$! The above line should be placed in BULLSTART.COM to be executed after
+$! every system reboot.
+$!
+$ IF F$SEARCH("SYS$HELP:BULL.HLB") .NES. "" THEN LIBRARY/DELETE=*/HELP SYS$HELP:BULL
+$ IF F$SEARCH("SYS$HELP:BULL.HLB") .EQS. "" THEN LIBRARY/CREATE/HELP SYS$HELP:BULL
+$ LIBRARY/HELP SYS$HELP:BULL BULLCOMS1,BULLCOMS2
+$ LIBRARY/HELP SYS$HELP:HELPLIB BULLETIN
diff --git a/decus/vmslt98a/bulletin/instruct.com b/decus/vmslt98a/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..273d3e9f0845774078d0dc4f53c720256671bcb2
--- /dev/null
+++ b/decus/vmslt98a/bulletin/instruct.com
@@ -0,0 +1,6 @@
+$ BULLETIN
+ADD/PERMANENT/SYSTEM INSTRUCT.TXT/NOEDIT
+INFO ON HOW TO USE THE BULLETIN UTILITY.
+ADD/PERMANENT NONSYSTEM.TXT/NOEDIT
+INFO ON BEING PROMPTED TO READ NON-SYSTEM BULLETINS.
+EXIT
diff --git a/decus/vmslt98a/bulletin/instruct.txt b/decus/vmslt98a/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6699642154414c70118a5de434037357572300db
--- /dev/null
+++ b/decus/vmslt98a/bulletin/instruct.txt
@@ -0,0 +1,8 @@
+This message is being displayed by the BULLETIN facility.  This is a non-DEC
+facility, so it is not described in the manuals.  Messages can be submitted by
+using the BULLETIN command.  System messages, such as this one, are displayed
+in full, but can only be entered by privileged users.  Non-system messages can
+be entered by anyone, but only their topics will be displayed at login time,
+and will be prompted to optionally read them.  (This prompting feature can be
+disabled).  All bulletins can be reread at any time unless they are deleted or
+expire.  For more information, see the on-line help (via HELP BULLETIN). 
diff --git a/decus/vmslt98a/bulletin/login.com b/decus/vmslt98a/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6707834c7c17009676b16fcc320a7f4c85e77a8
--- /dev/null
+++ b/decus/vmslt98a/bulletin/login.com
@@ -0,0 +1,31 @@
+$!
+$! The following line defines the BULLETIN command.
+$!
+$ BULL*ETIN :== $BULL_DIR:BULLETIN
+$!
+$! Note: The command prompt when executing the utility is named after
+$! the executable image.  Thus, as it is presently set up, the prompt
+$! will be "BULLETIN>".  DO NOT make the command that executes the
+$! image different from the image name, or certain things will break.
+$!
+$! If you would rather define the BULLETIN command using CDU rather than
+$! defining it using a symbol, use the BULLETIN.CLD file to do so.
+$!
+$! If you want to have more than one BULLETIN database, replace BULL_DIR
+$! with the actual directory to allow redefining BULL_DIR.  
+$!
+$! The following line causes new messages to be displayed upon logging in.
+$!
+$ BULLETIN/LOGIN/REVERSE
+$!
+$! If you wish bulletins to be displayed starting with
+$! the newest rather the oldest, omit the /REVERSE qualifier.
+$! Note that for totally new users, only permanent system messages and
+$! the first non-system general message is displayed (which, if you ran
+$! INSTURCT.COM, would describe what a non-system message is).
+$! This is done so as to avoid overwhelming a new user with lots of
+$! messages upon logging in for the first time.
+$! Users who have DISMAIL enabled in the authorzation table will automatically
+$! be set to "NOLOGIN" (see HELP SET NOLOGIN).  If you wish to disable this
+$! feature, add /ALL to the /LOGIN command.
+$!
diff --git a/decus/vmslt98a/bulletin/makefile b/decus/vmslt98a/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..303858dc5946421e4570fb4bad3593f78169c075
--- /dev/null
+++ b/decus/vmslt98a/bulletin/makefile
@@ -0,0 +1,82 @@
+# Makefile for BULLETIN
+ 
+Bulletin : Bulletin.Exe Bull.Hlb
+ 
+Bulletin.Exe : Bull.Olb
+   Link /NoTrace Bull.Olb/Lib /Inc=Bulletin$Main,Sys$System:Sys.Stb/Sel -
+        /NoUserlib /Exe=Bulletin.Exe,Sys$Input/Opt
+   ID="V2.24" $
+ 
+Bull.Olb : Bulletin.Obj Bulletin0.Obj Bulletin1.Obj Bulletin2.Obj  \
+           Bulletin3.Obj Bulletin4.Obj Bulletin5.Obj Bulletin6.Obj \
+           Bulletin7.Obj Bulletin8.Obj Bulletin9.Obj Bulletin10.Obj \
+           Bulletin11.Obj Bullcom.Obj Bullmain.Obj Allmacs.Obj
+   Library /Create Bull.Olb *.Obj
+   Purge /Log *.Obj,*.Exe
+ 
+Bulletin.Obj : Bulletin.For Bullfiles.Inc Bulldir.Inc Bullfolder.Inc \
+               Bulluser.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin.For
+ 
+Bulletin0.Obj : Bulletin0.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin0.For
+ 
+Bulletin1.Obj : Bulletin1.For Bulldir.Inc Bullfolder.Inc Bulluser.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin1.For
+ 
+Bulletin2.Obj : Bulletin2.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin2.For
+ 
+Bulletin3.Obj : Bulletin3.For Bulldir.Inc Bullfolder.Inc Bulluser.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin3.For
+ 
+Bulletin4.Obj : Bulletin4.For Bullfolder.Inc Bulluser.Inc Bullfiles.Inc \
+                Bulldir.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin4.For
+ 
+Bulletin5.Obj : Bulletin5.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin5.For
+ 
+Bulletin6.Obj : Bulletin6.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin6.For
+ 
+Bulletin7.Obj : Bulletin7.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin7.For
+ 
+Bulletin8.Obj : Bulletin8.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin8.For
+ 
+Bulletin9.Obj : Bulletin9.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin9.For
+ 
+Bulletin10.Obj : Bulletin10.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin10.For
+ 
+Bulletin11.Obj : Bulletin11.For Bulldir.Inc Bulluser.Inc Bullfolder.Inc \
+                Bullfiles.Inc Bullnews.Inc
+   Fortran /Extend /NoList Bulletin11.For
+ 
+Allmacs.Obj : Allmacs.mar
+   Macro   /NoList Allmacs.Mar
+ 
+Bullcom.Obj : Bullcom.cld
+   Set Command /Obj Bullcom.Cld
+ 
+Bullmain.Obj : Bullmain.cld
+   Set Command /Obj Bullmain.Cld
+ 
+Bull.Hlb : Bullcoms1.Hlp Bullcoms2.Hlp
+   Library /Create /Help Bull.Hlb Bullcoms1.Hlp, Bullcoms2.Hlp
+   Purge Bull.Hlb
+*.hlb :
+        lib/help/cre $*
diff --git a/decus/vmslt98a/bulletin/master.com b/decus/vmslt98a/bulletin/master.com
new file mode 100755
index 0000000000000000000000000000000000000000..112d981424b5777491b97a2ab82df7f864037a1c
--- /dev/null
+++ b/decus/vmslt98a/bulletin/master.com
@@ -0,0 +1,408 @@
+$ ! MASTER.COM - Initiate delivery of messages queued on a channel
+$ !
+$ ! Modification history and parameter definitions are at the end of this file.
+$ !
+$ set noon
+$ !
+$ ! Clean up and set up channel name, if on hold just exit
+$ !
+$ channel_name = f$edit(p1, "COLLAPSE,LOWERCASE")
+$ hold_list = "," + f$edit(f$logical("PMDF_HOLD"), "COLLAPSE,LOWERCASE") + ","
+$ if f$locate("," + channel_name + ",", hold_list) .lt. -
+     f$length(hold_list) then exit
+$ define/process pmdf_channel "''channel_name'"
+$ !
+$ ! Save state information, set up environment properly
+$ !
+$ save_directory = f$environment("DEFAULT")
+$ set default pmdf_root:[queue]
+$ save_protection = f$environment("PROTECTION")
+$ set protection=(s:rwed,o:rwed,g,w)/default
+$ save_privileges = f$setprv("NOSHARE")
+$ !
+$ if f$logical("PMDF_DEBUG") .eqs. "" then on control_y then goto out
+$ !
+$ ! Create listing of messages queued on this channel.
+$ !
+$ if p3 .eqs. "" then p3 = "1-JAN-1970"
+$ dirlst_file = "pmdf_root:[log]" + channel_name + "_master_dirlst_" + -
+  F$GETJPI ("", "PID") + ".tmp"
+$ define/process outbound 'dirlst_file'
+$ directory/noheader/notrailer/column=1/since="''p3'"/output='dirlst_file' -
+  pmdf_root:[queue]'channel_name'_*.%%;*
+$ !
+$ ! Determine whether or not connection should really be made
+$ !
+$ if p2 .nes. "POLL" .and. -
+     f$file_attributes(dirlst_file, "ALQ") .eq. 0 then goto out1
+$ !
+$ ! Handle various channels specially
+$ !
+$ if channel_name .eqs. "l" then goto local_channel
+$ if channel_name .eqs. "d" then goto DECnet_compatibility_channel
+$ if channel_name .eqs. "directory" then goto dir_channel
+$ if f$extract(0,5,channel_name) .eqs. "anje_"  then goto BITNET_channel
+$ if f$extract(0,4,channel_name) .eqs. "bit_"   then goto BITNET_channel
+$ if f$extract(0,5,channel_name) .eqs. "bull_"  then goto BULLETIN_channel
+$ if f$extract(0,3,channel_name) .eqs. "cn_"    then goto CN_channel
+$ if f$extract(0,5,channel_name) .eqs. "ctcp_"  then goto CTCP_channel
+$ if f$extract(0,3,channel_name) .eqs. "dn_"    then goto DECnet_channel
+$ if f$extract(0,6,channel_name) .eqs. "dsmtp_" then goto DSMTP_channel
+$ if f$extract(0,5,channel_name) .eqs. "etcp_"  then goto ETCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "ftcp_"  then goto FTCP_channel
+$ if f$extract(0,4,channel_name) .eqs. "ker_"   then goto KER_channel
+$ if f$extract(0,5,channel_name) .eqs. "mail_"  then goto MAIL_channel
+$ if f$extract(0,5,channel_name) .eqs. "mtcp_"  then goto MTCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "px25_"  then goto PX25_channel
+$ if f$extract(0,4,channel_name) .eqs. "tcp_"   then goto TCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "test_"  then goto TEST_channel
+$ if f$extract(0,5,channel_name) .eqs. "uucp_"  then goto UUCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "wtcp_"  then goto WTCP_channel
+$ if f$extract(0,6,channel_name) .eqs. "xsmtp_" then goto XSMTP_channel
+$ !
+$ ! This must be a PhoneNet channel (the default); set up and use MASTER
+$ !  Read the list of valid connection types for each channel.
+$ !
+$ cnt = f$integer("0")
+$ open/read/error=regular_master pmdf_data pmdf_root:[table]phone_list.dat
+$       list_loop:
+$               read/end=eof_list pmdf_data line
+$ !  Ignore comment lines.
+$               if (f$extract (0, 1, line) .eqs. "!") then -
+                        goto list_loop
+$               line = f$edit (line, "COMPRESS,LOWERCASE")
+$ !  Get the channel name from the line read.
+$               chan = f$extract (0, f$locate(" ", line), line)
+$               if (chan .nes. channel_name) then -
+$                       goto list_loop
+$ !  Get the connection name
+$               name = f$edit(f$extract(f$locate(" ",line),255,line),"COLLAPSE")
+$ !  If none, then ignore the line
+$               if name .eqs. "" then -
+                        goto list_loop
+$ !  Found at least one to try.
+$               cnt = cnt + 1
+$               @pmdf_root:[exe]all_master.com 'name'
+$               define PMDF_DEVICE TT
+$ !
+$ ! Define other logical names
+$ !
+$ define/user script             pmdf_root:[table.'channel_name']'name'_script.
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ !
+$ !   This check attempts to verify that we are in fact the owner process of
+$ !   the device, TT.  If the device is sharable, then we ignore the
+$ !   owner.
+$ !
+$ if (f$getdvi("TT","pid") .nes. f$getjpi(0,"pid")) .and. -
+     (f$getdvi("TT","shr") .eqs. "FALSE") then -
+        goto list_loop
+$ !
+$ !  Run master to deliver the mail
+$ !
+$ run pmdf_root:[exe]master
+$ exit_stat = $status
+$ !
+$ ! Activate optional cleanup script to reset terminal/modem
+$ !
+$ if f$search("pmdf_root:[exe]''name'_cleanup.com") .nes. "" then -
+     @pmdf_root:[exe]'name'_cleanup.com 'exit_stat'
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ !
+$ !  If master does not exit normally, then try a different connection.
+$ !
+$ if exit_stat .ne. 1 then goto list_loop
+$ eof_list:
+$ close pmdf_data
+$ !
+$ !  If we found at least one connection type for this channel, then skip
+$ !  the attempt to use the conventional mechanism.
+$ !
+$ if cnt .gt. 0 then goto out_phonenet
+$ !
+$ regular_master:
+$ @pmdf_root:[exe]'channel_name'_master.com
+$ define PMDF_DEVICE TT
+$ !
+$ !  Define logical names
+$ !
+$ define/user script             pmdf_root:[table]'channel_name'_script.
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ !
+$ run pmdf_root:[exe]master
+$ exit_stat = $status
+$ !
+$ !  Activate optional cleanup script to reset terminal/modem
+$ !
+$ if f$search("''channel_name'_cleanup.com") .nes. "" then -
+     @pmdf_root:[exe]'channel_name'_cleanup.com 'exit_stat'
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ !
+$ out_phonenet:
+$ if P4 .eqs. "POST" then wait 00:00:30
+$ goto out1
+$ !
+$ ! Directory channel
+$ !
+$ dir_channel:
+$ !
+$ run pmdf_root:[exe]dir_master
+$ goto out1
+$ !
+$ ! This is a DECnet channel; set up and use DN_MASTER
+$ !
+$ DECnet_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ node_name = f$edit(channel_name - "dn_", "UPCASE")
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ define/user pmdf_node          "''node_name'::""PMDF="""
+$ !
+$ run pmdf_root:[exe]dn_master
+$ goto out1
+$ !
+$ ! This is a BITNET channel; use BN_MASTER
+$ !
+$ BITNET_channel:
+$ !
+$ if channel_name .eqs. "bit_gateway" then goto BITNET_gateway
+$ run pmdf_root:[exe]bn_master
+$ goto out1
+$ !
+$ ! This is the BITNET gateway channel; use BN_GATEWAY
+$ !
+$ BITNET_gateway:
+$ !
+$ run pmdf_root:[exe]bn_gateway
+$ goto out1
+$ !
+$ ! This is a BULLETIN channel; use BULLETIN_MASTER
+$ !
+$ BULLETIN_channel:
+$ !
+$ run pmdf_root:[exe]bulletin_master
+$ goto out1
+$ !
+$ ! This is a Tektronix TCP channel; use TCP_MASTER
+$ !
+$ TCP_channel:
+$ !
+$ run pmdf_root:[exe]tcp_master
+$ goto out1
+$ !
+$ ! This is a CMU/Tektronix TCP channel; use CTCP_MASTER
+$ !
+$ CTCP_channel:
+$ !
+$ run pmdf_root:[exe]ctcp_master
+$ goto out1
+$ !
+$ ! This is a Wollongong TCP channel; use WTCP_MASTER
+$ !
+$ WTCP_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ run pmdf_root:[exe]wtcp_master
+$ goto out1
+$ !
+$ ! This is a MultiNet TCP channel; use MTCP_MASTER
+$ !
+$ MTCP_channel:
+$ !
+$ run pmdf_root:[exe]mtcp_master
+$ goto out1
+$ !
+$ ! This is a Excelan TCP channel; use ETCP_MASTER
+$ !
+$ ETCP_channel:
+$ !
+$ run pmdf_root:[exe]etcp_master
+$ goto out1
+$ !
+$ ! This is an NRC Fusion TCP channel; use FTCP_MASTER
+$ !
+$ FTCP_channel:
+$ !
+$ run pmdf_root:[exe]ftcp_master
+$ goto out1
+$ !
+$ CN_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ define/user script             pmdf_root:[table]'channel_name'_script.
+$ ! following may vary: should point to cnio's group
+$ define/table=lnm$process_directory lnm$temporary_mailbox lnm$group_000277
+$ !
+$ run/nodeb'p5' pmdf_root:[exe]cn_smtp_master
+$ goto out1
+$ !
+$ KER_channel:
+$ !
+$ ! kermit protocol is slave only. If we get here there has been a mistake.
+$ ! however we will just exit and no harm done.
+$ goto out1
+$ !
+$ ! This is a PhoneNet X25 channel; set up and use PX25_MASTER
+$ !
+$ PX25_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]'channel_name'_di_master.trn
+$ define/user ph_logfile         pmdf_root:[log]'channel_name'_ph_master.log
+$ define/user di_errfile         pmdf_root:[log]'channel_name'_di_master.log
+$ !
+$ run pmdf_root:[exe]PX25_master
+$ goto out1
+$ !
+$ ! This is a DEC/Shell channel; set up and use UUCP_MASTER
+$ !
+$ UUCP_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ uucp_to_host = channel_name - "uucp_"
+$ define/user uucp_to_host       "''uucp_to_host'"
+$ define/user uucp_current_message -
+  pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user uucp_logfile       pmdf_root:[log]'channel_name'_master.logfile
+$ !
+$ run pmdf_root:[exe]UUCP_master
+$ uupoll = "$shell$:[usr.lib.uucp]uupoll"
+$ uupoll 'uucp_to_host'
+$ goto out1
+$ !
+$ ! This is a X.25 SMTP channel; set up and use XSMTP_MASTER
+$ !
+$ XSMTP_channel:
+$ !
+$ run pmdf_root:[exe]xsmtp_master
+$ goto out1
+$ !
+$ ! This is a DECNET SMTP channel; set up and use DSMTP_MASTER
+$ !
+$ DSMTP_channel:
+$ !
+$ run pmdf_root:[exe]dsmtp_master
+$ goto out1
+$ !
+$ ! Handle delivery on the local channel, MAIL_ channels, and
+$ ! the DECnet compatibility channel
+$ !
+$ MAIL_channel:
+$ local_channel:
+$ DECnet_compatibility_channel:
+$ open/read queue_file 'dirlst_file'
+$ local_loop:
+$   read/end=exit_local_loop/error=exit_local_loop  queue_file file_to_process
+$   priv_list = f$setprv("SYSPRV, DETACH")
+$   mail/protocol=pmdf_mailshr 'file_to_process'
+$   priv_list = f$setprv(priv_list)
+$ goto local_loop
+$ !
+$ exit_local_loop:
+$ close queue_file
+$ goto out1
+$ !
+$ ! This is a SMTP test channel, use TEST_SMTP_MASTER
+$ !
+$ TEST_channel:
+$ !
+$ ! Typically some form of redirection is needed here...
+$ deassign sys$input
+$ run pmdf_root:[exe]test_smtp_master
+$ goto out1
+$ !
+$ out1:
+$ delete 'dirlst_file';*
+$ !
+$ ! Common exit point - clean up things first
+$ !
+$ out:
+$ if f$logical("OUTBOUND") .nes. "" then deassign/process outbound
+$ if f$logical("PMDF_CHANNEL") .nes. "" then deassign/process pmdf_channel
+$ if f$logical("PMDF_DATA") .nes. "" then close pmdf_data
+$ if f$logical("PMDF_DEVICE") .eqs. "" then goto restore
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ restore:
+$ !
+$ ! Restore saved stuff
+$ !
+$ set protection=('save_protection')/default
+$ set default 'save_directory'
+$ set process/priv=('save_privileges')
+$ !
+$ exit
+$ !
+$ ! Modification history:
+$ !
+$ ! This version by Ned Freed, 20-Jul-1986
+$ !
+$ ! Modified by Gregg Wonderly to allow multiple connections for each channel
+$ !   10-Oct-1986.
+$ ! Some additions by Ned Freed 30-Oct-86.
+$ ! Added CMU/Tektronix TCP channel (CTCP) /Kevin Carosso 6-Mar-1987
+$ ! Added Multinet TCP channel (MTCP) /Ned Freed 10-Mar-1987
+$ ! Added directory save/restore /Ned Freed 1-Jun-1987
+$ ! Added Excelan TCP channel (ETCP) /Ned Freed 9-Jul-1987
+$ ! Added MAIL, CNIO, KERMIT channel /Bob Smart 4-Jul-1987
+$ ! Added Warwick Jackson's PhoneNet X25 support /Ned Freed 5-Sep-87
+$ ! Added X25 SMTP channel SX25_ /Goeran Bengtsson, Mats Sundvall 24-Jul-87
+$ ! Added NRC Fusion TCP channel (FTCP) /Kevin Carosso 12-Jan-1988
+$ ! Added a variant of Randy McGee's code to put a list of channels on hold
+$ !   /Ned Freed 9-Feb-1988
+$ ! Made this procedure save and restore a little more state information
+$ !   than it used to, including default protection and privileges. Also
+$ !   moved a bunch of the logical name assignments around to eliminate
+$ !   redundant code all over the place. /Ned Freed 10-Feb-1988
+$ ! Modified to allow P3 date/time paramter. /Ned Freed 23-Feb-1988
+$ ! Added support for Dennis Boylan's UUCP channel. /Ned Freed 28-Mar-1988
+$ ! Added Robert Smart's directory channel. /Ned Freed 21-Apr-1988
+$ ! Added support for Warwick Jackson's SMTP over X.25 and SMTP over
+$ !   DECnet channels. /Ned Freed 26-May-1988
+$ ! Added P4 and P5 parameters. /Ned Freed 10-Jun-1988
+$ ! Added code to call the TEST_SMTP_MASTER for testing. /Ned Freed 1-Jul-1988
+$ ! Added preliminary support for ANJE. /Ned Freed 7-Jul-1988
+$ ! Removed extra dispatch for WTCP_ channel. /Ned Freed 3-Sep-1988
+$ ! Added dispatch for BULL_ channel. /Ned Freed 28-Nov-1988
+$ ! Cleaned up error recovered and emergency exit -- close PHONE_LIST.DAT
+$ !   file when aborting. /Ned Freed 13-Dec-1988
+$ ! Additional error recovery cleanup -- use PMDF_DEVICE instead of TT to
+$ !   allow deallocation on an abort. /Ned Freed 14-Dec-1988
+$ !
+$ ! Parameters:
+$ !
+$ !   P1 - Name of the channel whose messages are to be delivered.
+$ !   P2 - Activity type. If P2 .eqs. "POLL", establish the connection
+$ !        unconditionally, otherwise only establish the connection if
+$ !        messages are waiting in the queue.
+$ !   P3 - Earliest possible date/time for message(s). Messages older than
+$ !        this time are not processed.
+$ !   P4 - Environment. P4 .eqs. "POST" if MASTER is being called from the
+$ !        POST.COM procedure or some other procedure that invokes MASTER
+$ !        more than once. This parameter is used to insert delays before
+$ !        returning if hardware needs time to reset.
+$ !   P5 - Parameter reserved for channel-specific uses.
diff --git a/decus/vmslt98a/bulletin/mx.com b/decus/vmslt98a/bulletin/mx.com
new file mode 100755
index 0000000000000000000000000000000000000000..141e70668e08d8012dcc4917c6865d6a1b3aa37d
--- /dev/null
+++ b/decus/vmslt98a/bulletin/mx.com
@@ -0,0 +1,958 @@
+$set nover
+$copy/log sys$input BUILD_MX_BULL.COM
+$deck
+$ save_verify = 'f$verify(0)'
+$!
+$!  Command file to build MX_BULL (MX SITE transport for BULLETIN)
+$!
+$ say := write sys$output
+$ if f$trnlnm("BULL_SOURCE") .eqs. ""
+$ then	say "BULL_SOURCE logical not defined; must point to BULL.OLB directory"
+$	exit
+$ endif
+$ say "Compiling MX_BULL...."
+$ cc mx_bull
+$ say "Linking MX_BULL...."
+$ link/notrace mx_bull,bull_source:BULL.OLB/LIB,sys$input/option
+SYS$SHARE:VAXCRTL.EXE/SHARE
+$ say "Build of MX_BULL.EXE completed"
+$ exit f$verify(save_verify).or.1
+$eod 
+$copy/log sys$input MX_BULL.C
+$deck
+#module MX_BULL "01-001"
+/*
+ *
+ *  Program:	MX_BULL
+ *
+ *  Author:	Hunter Goatley
+ *		Academic Computing, STH 226
+ *		Western Kentucky University
+ *		Bowling Green, KY 42101
+ *		goathunter@wkuvx1.bitnet
+ *		502-745-5251
+ *
+ *  Date:	March 8, 1991
+ *
+ *  Functional description:
+ *
+ *	This program serves as an MX SITE transport to transfer incoming
+ *	mail files to UALR's BULLETIN.
+ *
+ *	The MX_SITE delivery agent takes messages routed to a SITE path and
+ *	feeds them into a subprocess that executes a command procedure named
+ *	MX_EXE:SITE_DELIVER.COM.  There are three parameters passed to the
+ *	the command procedure:
+ *
+ *		P1	- The name of a temporary file containing the message
+ *			  text, including all of the RFC822 headers
+ *			  (corresponding to the DATA part of an SMTP
+ *			  transaction).
+ *		P2	- The name of a temporary file containing a list of
+ *			  a messages recipients, which corresponds to the
+ *			  RCPT_TO addresses of an SMTP transaction.
+ *		P3	- The RFC822 address of the sender of the message,
+ *			  which corresponds to the MAIL FROM address of an
+ *			  SMTP transaction.
+ *
+ *	This program expects the same parameters, except that the third
+ *	parameter is optional.  If the third parameter is omitted, BULLETIN
+ *	will scan the RFC822 headers in the message for a "From:" line.
+ *	If the third parameter is specified, it is expected to be a file
+ *	specification.  It is assumed that SITE_DELIVER.COM has written the
+ *	address to this file.
+ *
+ *	The logical MX_BULLETIN_POSTMASTER can be defined as a local
+ *	username to receive error notices.  If BULLETIN returns an error
+ *	while trying to add a message, and the MX_BULLETIN_POSTMASTER
+ *	is defined as a valid local username, the message will be mailed
+ *	to that user for further handling.
+ *
+ *	MX_BULLETIN_POSTMASTER must be defined system-wide in executive mode:
+ *
+ *		$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
+ *
+ *  Modification history:
+ *
+ *	01-001		Hunter Goatley		14-MAR-1991 14:41
+ *		Added scan_for_from_line, which scans the message's RFC822
+ *		headers for the "From:" line.  General cleanup on a few
+ *		routines.  MX_BULL now provides an RESPOND-able address in
+ *		BULLETIN.
+ *
+ *	01-000		Hunter Goatley		 8-MAR-1991 07:20
+ *		Genesis.
+ *
+ */
+
+/*  Include all needed structures and constants  */
+
+#include descrip
+#include lib$routines
+#include libdef
+#include lnmdef
+#include maildef
+#include rms
+#include ssdef
+#include str$routines
+#include string
+
+/* Declare the external BULLETIN routines that we call */
+
+unsigned long int INIT_MESSAGE_ADD();
+unsigned long int WRITE_MESSAGE_LINE();
+unsigned long int FINISH_MESSAGE_ADD();
+
+/* Define some macros to make things a little easier */
+
+#define rms_get(rab) ((rms_status = SYS$GET(rab)))
+#define err_exit(stat) {traceerr(stat); return(stat);}
+#define vms_errchk2() if(!(vms_status&1)) err_exit(vms_status);
+#define vms_errchk(func) {vms_status=func; vms_errchk2();}
+
+#define tracemsg(msg) if (trace) printf("MX_BULL: %s\n",msg);
+#define traceerr(msg) if (trace) printf("MX_BULL: Error status %%X%08x\n",msg);
+
+/* Define some global variables to make things easy */
+
+struct FAB msgfab;				/* FAB for message text */
+struct RAB msgrab;				/* RAB for message text */
+struct FAB rcptfab;				/* FAB for recipients file */
+struct RAB rcptrab;				/* RAB for recipients file */
+struct FAB fromfab;				/* FAB for FROM file */
+struct RAB fromrab;				/* RAB for FROM file */
+char msgbuf[512];				/* Input buffer for msgrab */
+char rcptbuf[512];				/* Input buffer for rcptrab */
+char frombuf[512];				/* Input buffer for frombuf */
+short trace;
+unsigned long int rms_status;			/* Status of RMS calls */
+unsigned long int vms_status;			/* Status of other calls */
+
+static $DESCRIPTOR(lnm_table,"LNM$SYSTEM_TABLE");
+
+#define itmlstend {0,0,0,0}			/* An empty item list */
+typedef struct itmlst				/* An item list structure */
+{
+  short buffer_length;
+  short item_code;
+  long buffer_address;
+  long return_length_address;
+} ITMLST;
+
+ITMLST
+  nulllist[] = {itmlstend};
+
+ITMLST
+  address_itmlst[] = {				/* MAIL$SEND_ADD_ADDRESS */
+	{0, MAIL$_SEND_USERNAME, 0, 0},
+	itmlstend},
+  bodypart_itmlst[] = {				/* MAIL$SEND_ADD_BODYPART */
+	{0, MAIL$_SEND_RECORD, 0, 0},
+	itmlstend},
+  attribute_itmlst[] = {			/* MAIL$SEND_ADD_ATTRIBUTE */
+	{0, MAIL$_SEND_TO_LINE, 0, 0},
+	{0, MAIL$_SEND_FROM_LINE, 0, 0},
+	{0, MAIL$_SEND_SUBJECT, 0, 0},
+	itmlstend}
+  ;
+
+ITMLST
+  trnlnm_itmlst[] = {				/* $TRNLNM item list */
+	{0, LNM$_STRING, 0, 0},
+	itmlstend}
+  ;
+
+
+/*
+ *
+ *  Function:	open_file_rms
+ *
+ *  Functional description:
+ *
+ *	This routine opens a sequential text file in VMS "normal text" file
+ *	format.  It uses RMS to open the file.
+ *
+ *  Inputs:
+ *
+ *	infab	- Address of the input FAB
+ *	inrab	- Address of the input RAB
+ *	buff	- Address of the input buffer
+ *	filename - Address of the filename to open (ASCIZ)
+ *
+ *  Outputs:
+ *
+ *	fab and rab are modified if file is opened.
+ *
+ *  Returns:
+ *
+ *	RMS status
+ *
+ */
+unsigned long int
+open_file_rms (struct FAB *infab, struct RAB *inrab, char *buff, char *filename)
+{
+    unsigned long int rms_status;
+
+    *infab = cc$rms_fab;			/* Initialize the FAB */
+    *inrab = cc$rms_rab;			/* Initialize the RAB */
+    infab->fab$b_fns = strlen(filename);	/* Set filename length */
+    infab->fab$l_fna = filename;		/* Set filename address */
+    infab->fab$b_fac = FAB$M_GET;		/* GET access only */
+    infab->fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
+    inrab->rab$l_fab = infab;			/* Let RAB point to FAB */
+    inrab->rab$b_rac = RAB$C_SEQ;		/* Sequential file access */
+    inrab->rab$w_usz = 512;			/* Record size is 512 bytes */
+    inrab->rab$l_ubf = buff;			/* Read to this buffer */
+
+    rms_status = SYS$OPEN (infab);		/* Open the file */
+    if (!(rms_status & 1))			/* If an error occurs, return */
+	return (rms_status);			/* ... a status */
+    rms_status = SYS$CONNECT (inrab);		/* Connect the RAB */
+    return (rms_status);			/* Return the RMS status */
+}
+
+/*
+ *
+ *  Function:	init_sdesc
+ *
+ *  Functional description:
+ *
+ *	Initialize a static string descriptor.
+ *
+ *  Inputs:
+ *
+ *	sdesc	- Address of the descriptor to initialize
+ *		  (of type struct dsc$descriptor_s)
+ *	string	- Address of null-terminated string the descriptor describes
+ *
+ *  Outputs:
+ *
+ *	sdesc	- Descriptor passed as sdesc is initialized
+ *
+ */
+void
+init_sdesc (struct dsc$descriptor_s *sdesc, char *string)
+{
+    sdesc->dsc$w_length = strlen(string);	/* Set the length	*/
+    sdesc->dsc$b_dtype = DSC$K_DTYPE_T;		/* Type is text		*/
+    sdesc->dsc$b_class = DSC$K_CLASS_S;		/* Class is static	*/
+    sdesc->dsc$a_pointer = string;		/* Point to the string	*/
+}
+
+/*
+ *
+ *  Function:	add_to_bulletin_folder
+ *
+ *  Functional description:
+ *
+ *	Adds a message to a BULLETIN folder by calling the external
+ *	BULLETIN routines INIT_MESSAGE_ADD, WRITE_MESSAGE_LINE, and
+ *	FINISH_MESSAGE_ADD.
+ *
+ *	The following constants are (may be) passed to INIT_MESSAGE_ADD:
+ *
+ *		Subject = "" 	Causes BULLETIN to scan RFC822 headers for
+ *				a "Subject:" or "Subj:" line
+ *		From = "MX%"	Causes BULLETIN to scan RFC822 headers for
+ *				a "Reply-to:" or "From:" line
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - RMS status of call to INIT_MESSAGE_ADD
+ *
+ */
+unsigned long int
+add_to_bulletin_folder(struct RAB *filerab, void *folder, void *from)
+{
+    unsigned long int bull_status;	/* Status from INIT_MESSAGE_ADD */
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    static $DESCRIPTOR(subject,"");	/* Subject is "" */
+
+    /* Call BULLETIN routine to initialize adding the message */
+
+    INIT_MESSAGE_ADD (folder, from, &subject, &bull_status);
+
+    if (!(bull_status & 1)){					/* Error? */
+	return(bull_status);
+    }
+
+    /*	Loop reading message lines until end-of-file.  For each line read,
+	create a string descriptor for it and call the BULLETIN routine to
+	add the line. */
+
+    while (rms_get(filerab) != RMS$_EOF){		/* Loop until EOF */
+	filerab->rab$l_rbf[filerab->rab$w_rsz] = 0;	/* End byte = NULL */
+	init_sdesc(&msg_line, filerab->rab$l_rbf);	/* Now build desc. */
+	WRITE_MESSAGE_LINE (&msg_line);			/* Add to BULLETIN */
+    }
+
+    FINISH_MESSAGE_ADD();		/* Call BULLETIN routine to finish */
+
+    tracemsg("Message added to folder");
+    return(SS$_NORMAL);			/* Return success to caller */
+}
+
+
+/*
+ *
+ *  Function:	scan_for_from_line
+ *
+ *  Functional description:
+ *
+ *	The routine scans the message's RFC822 headers for the "From:" line.
+ *	It parses out the address by extracting the <address>.
+ *
+ *	This routine was necessary because letting BULLETIN find the "From:"
+ *	line was resulting in a non-RESPONDable address for MX.  For example,
+ *	BULLETIN was creating:
+ *
+ *		From: MX%"Hunter Goatley, WKU <goathunter@WKUVX1.BITNET>"
+ *
+ *	but MX needs
+ *
+ *		From: MX%"<goathunter@WKUVX1.BITNET>"
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *
+ *  Outputs:
+ *
+ *	final_from - Address of a character buffer to receive the final address
+ *
+ *  Returns:
+ *
+ *	unsigned long int - binary success/failure status
+ *
+ *  Side effects:
+ *
+ *	The message file is rewound so that subsequent GETs start at the
+ *	beginning of the message.
+ *
+ */
+unsigned long int
+scan_for_from_line(struct RAB *filerab, char *final_from)
+{
+    unsigned long int scan_status;	/* Status from INIT_MESSAGE_ADD */
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    char whole_from_line[512];		/* The assembled "From:" line */
+    char *filebuffer;			/* Pointer to the input buffer */
+    int i, j, x;			/* Work variables */
+
+    scan_status = SS$_NORMAL;			/* Assume success */
+    whole_from_line[0] = '\0';			/* Initialize work buffer */
+
+    /*	Loop reading message lines until end-of-file or first null line,
+	which should signal the end of the RFC822 header.  For each line read,
+	check to see if we've located the "From:" line.
+    */
+
+    filebuffer = filerab->rab$l_ubf;			/* Init buffer ptr */
+    while ((rms_get(filerab) != RMS$_EOF) &&		/* Loop until EOF */
+	   ((x = filerab->rab$w_rsz) != 0)){		/* or null record */
+	filebuffer[x] = '\0';				/* Set NULL byte */
+	if (strncmp(filebuffer,"From:",5)==0){		/* Is it the "From:"? */
+
+	   /* Found "From:" line */
+	   tracemsg("Found \042From:\042 line in RFC822 header");
+	   strcpy(whole_from_line,filebuffer);		/* Copy to work buff */
+
+	   /* The "From:" line may actually be split over several lines.
+	      In such cases, the remaining lines are indented by 6 spaces.
+	      To handle this, loop reading records until one is read that
+	      doesn't begin with a blank.  As each record is read, it is
+	      trimmed and tacked on to whole_from_line, so we end up with
+	      the entire "From:" line in one buffer.  */
+
+	   while((rms_get(filerab) != RMS$_EOF) &&	/* Read rest of From: */
+		 (filebuffer[0] == ' ')){		/* ... line */
+	      for (i = 0; filebuffer[i] == ' '; ++i);	/* Step over blanks */
+	      strcat(whole_from_line,&filebuffer[i]);	/* Tack it on end */
+	   }
+
+	   /* Now have the whole "From:" line in whole_from_line.  Since
+	      the real address is enclosed in "<>", look for it by
+	      searching for the last "<" and reading up to the ">".  */
+
+	   i = strrchr(whole_from_line,'<');		/* Find last "<" */
+	   if (i != 0){					/* Found it.... */
+		j = strchr(i,'>');			/* Find last ">" */
+	        j = j-i+1;				/* Calc addr length */
+	   }
+	   else{
+		j = strlen(whole_from_line)-6;		/* Don't count From: */
+		i = &whole_from_line + 6;		/* in string length */
+	   }
+	   if (j < 0){					/* If neg., error */
+		tracemsg("Error - unable to locate from address");
+		strcpy(final_from,"");			/* Return null string */
+		scan_status = 0;			/* Set error status */
+	   }
+	   else {
+		tracemsg("Found sender's address in RFC822 header");
+		strncpy(final_from, i, j);		/* Copy to caller */
+	   }	
+	}
+    }
+
+    SYS$REWIND(filerab);		/* Rewind the file to the beginning */
+    return(scan_status);		/* Return success to caller */
+}
+
+
+/*
+ *
+ *  Function:	forward_to_postmaster
+ *
+ *  Functional description:
+ *
+ *	If an error occurs trying to write a message to a BULLETIN folder,
+ *	this routine is called to forward the message to the local
+ *	postmaster.
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *	status	- Address of longword containing the BULLETIN error code
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - binary status of call to INIT_MESSAGE_ADD
+ *
+ *  Side effects:
+ *
+ *	The message file is rewound so that subsequent calls to this routine
+ *	can be made (in case the message is to be written to several folders).
+ *
+ */
+unsigned long int
+forward_to_postmaster(struct RAB *filerab, void *folder, void *from, int status)
+{
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    struct dsc$descriptor_s subject;
+    char subject_buf[256];
+    char postmaster[256];   int postmaster_len;
+    char status_msg_buf[256];   int status_msg_len;
+    struct dsc$descriptor_s status_msg;
+    static $DESCRIPTOR(faostr,"Failed BULLETIN message for folder !AS");
+    static $DESCRIPTOR(MXBULL,"MX->SITE (BULLETIN delivery)");
+    static $DESCRIPTOR(postmaster_lnm,"MX_BULLETIN_POSTMASTER");
+    int send_context = 0;  int x;  int y;
+
+    static char *error_msgs[] = {
+	{"Error delivering message to BULLETIN folder.  BULLETIN error status:"},
+	{""},
+	{""},
+	{"Original message text follows:"},
+	{"--------------------------------------------------"}
+    };
+
+    trnlnm_itmlst[0].buffer_length = 255;
+    trnlnm_itmlst[0].buffer_address = &postmaster;
+    trnlnm_itmlst[0].return_length_address = &postmaster_len;
+
+    SYS$TRNLNM( 0, &lnm_table, &postmaster_lnm, 0, trnlnm_itmlst);
+    if (postmaster_len == 0)		/* If logical is not defined, */
+	return(SS$_NORMAL);		/* then pretend it worked     */
+
+    tracemsg("Forwarding message to local postmaster....");
+    subject.dsc$w_length = 255;
+    subject.dsc$a_pointer = &subject_buf;
+    SYS$FAO(&faostr, &subject, &subject, folder);	/* Format the subject */
+
+    address_itmlst[0].buffer_length = postmaster_len;		   /* To: */
+    address_itmlst[0].buffer_address = &postmaster;		   /* To: */
+    attribute_itmlst[0].buffer_length = postmaster_len;		   /* To: */
+    attribute_itmlst[0].buffer_address = &postmaster;		   /* To: */
+    attribute_itmlst[1].buffer_length = MXBULL.dsc$w_length;	   /* From: */
+    attribute_itmlst[1].buffer_address = MXBULL.dsc$a_pointer;	   /* From: */
+    attribute_itmlst[2].buffer_length = subject.dsc$w_length;	   /* Subject:*/
+    attribute_itmlst[2].buffer_address = subject.dsc$a_pointer;	   /* Subject:*/
+
+    vms_errchk(mail$send_begin(&send_context, &nulllist, &nulllist));
+    vms_errchk(mail$send_add_address(&send_context, &address_itmlst,
+			&nulllist));
+    vms_errchk(mail$send_add_attribute(&send_context, &attribute_itmlst,
+			&nulllist));
+
+    for (x = 0; x < 5; x++){
+	bodypart_itmlst[0].buffer_length = strlen(error_msgs[x]);
+	bodypart_itmlst[0].buffer_address = error_msgs[x];
+	vms_errchk(mail$send_add_bodypart(&send_context,
+		&bodypart_itmlst, &nulllist));
+	if (x == 1){
+	  status_msg.dsc$w_length = 256;
+	  status_msg.dsc$b_dtype = DSC$K_DTYPE_T;
+	  status_msg.dsc$b_class = DSC$K_CLASS_S;
+	  status_msg.dsc$a_pointer = &status_msg_buf;
+	  y = SYS$GETMSG (status, &status_msg, &status_msg, 15, 0);
+	  if (!(y & 1))
+	     sprintf(status_msg_buf,"Error code is %%X%08x",status);
+	  else
+	     status_msg_buf[status_msg.dsc$w_length] = '\0';
+	  bodypart_itmlst[0].buffer_length = strlen(status_msg_buf);
+	  bodypart_itmlst[0].buffer_address = &status_msg_buf;
+	  vms_errchk(mail$send_add_bodypart(&send_context,&bodypart_itmlst,
+		&nulllist));
+	}
+    }
+
+    while (rms_get(filerab) != RMS$_EOF){		/* Loop until EOF */
+	bodypart_itmlst[0].buffer_length = filerab->rab$w_rsz;
+	bodypart_itmlst[0].buffer_address = filerab->rab$l_rbf;
+	vms_errchk(mail$send_add_bodypart(&send_context,
+		&bodypart_itmlst, &nulllist));
+    }
+
+    vms_errchk(mail$send_message(&send_context, &nulllist, &nulllist));
+    vms_errchk(mail$send_end(&send_context, &nulllist, &nulllist));
+
+    tracemsg("Message forwarded to postmaster....");
+}
+
+
+/*
+ *
+ *  Function:	log_accounting
+ *
+ *  Functional description:
+ *
+ *	This routine will write an accounting record for the message.
+ *
+ *  Inputs:
+ *
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *	status	- Address of longword containing the BULLETIN error code
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - RMS status
+ *
+ */
+unsigned long int
+log_accounting(void *folder, void *from, int bull_status)
+{
+    struct FAB accfab;
+    struct RAB accrab;
+    static $DESCRIPTOR(MX_BULL_ACCNTNG,"MX_BULLETIN_ACCNTNG");
+    static $DESCRIPTOR(faostr,
+	"!%D MX_BULL: FOLDER=\042!AS\042, ORIGIN=\042!AS\042, STATUS=%X!XL");
+    char outbufbuf[256];
+    struct dsc$descriptor_s outbuf = {256, DSC$K_DTYPE_T, DSC$K_CLASS_S,
+		 &outbufbuf};
+
+    int status;
+    static char bullacc[] = "MX_BULLETIN_ACC";
+    static char bullaccdef[] = "MX_SITE_DIR:.DAT";
+
+    status = SYS$TRNLNM( 0, &lnm_table, &MX_BULL_ACCNTNG, 0, 0);
+    if (!(status & 1))
+	return(SS$_NORMAL);
+
+    tracemsg("Writing accounting information to accounting log....");
+    accfab = cc$rms_fab;
+    accrab = cc$rms_rab;
+    accfab.fab$b_fns = strlen(bullacc);		/* Set filename length */
+    accfab.fab$l_fna = &bullacc;		/* Set filename address */
+    accfab.fab$b_dns = strlen(bullaccdef);	/* Set filename length */
+    accfab.fab$l_dna = &bullaccdef;		/* Set filename address */
+    accfab.fab$b_fac = FAB$M_PUT;		/* PUT access only */
+    accfab.fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
+    accfab.fab$b_rfm = FAB$C_VAR;		/* Variable length records */
+    accfab.fab$b_rat = FAB$M_CR;		/* Normal "text" rat */
+    accrab.rab$l_fab = &accfab;			/* Let RAB point to FAB */
+    accrab.rab$b_rac = RAB$C_SEQ;		/* Sequential file access */
+
+    status = SYS$OPEN (&accfab);		/* Try to open the file */
+    if (status & 1)				/* Success? */
+	accrab.rab$l_rop = RAB$M_EOF;		/* Set to EOF */
+    else					/* Couldn't open, so create */
+	status = SYS$CREATE (&accfab);		/* ... a new one */
+    if (status & 1){				/* If either was OK... */
+	status = SYS$CONNECT (&accrab);		/* Connect the RAB */
+	if (status == RMS$_EOF)			/* RMS$_EOF status is OK */
+	   status = RMS$_NORMAL;		/* Change it to NORMAL */
+	if (!(status & 1)){			/* If any error occurred */
+	   tracemsg("Unable to open accounting file");
+	   traceerr(status);
+	   SYS$CLOSE (&accfab);			/* Close the file */
+	   return(status);			/* And return the error */
+	}
+    }
+    else
+	return(status);
+
+    SYS$FAO(&faostr, &outbuf, &outbuf, 0, folder, from, bull_status);
+    accrab.rab$w_rsz = outbuf.dsc$w_length;
+    accrab.rab$l_rbf = outbuf.dsc$a_pointer;
+    SYS$PUT (&accrab);
+    SYS$CLOSE (&accfab);
+}
+
+/*
+ * 
+ *  Main routine
+ *
+ */
+main(int argc, char *argv[])
+{
+  struct dsc$descriptor_s folder;	/* Descriptor for the folder name */
+  struct dsc$descriptor_s from_user;	/* Descriptor for "From:" line */
+  static $DESCRIPTOR(MX_SITE_DEBUG,"MX_SITE_DEBUG");
+
+  char *from_line;			/* Pointer to dynamic "From:" buffer */
+  char *folder_name;			/* Pointer to folder name in rcptbuf */
+  char *atsign;				/* Pointer to "@" in rcptbuf */
+  int  x;				/* Work variable */
+  unsigned long int bull_status;	/* Status from add_to_bulletin_folder */
+
+  --argc;				/* Don't count the program name */
+  if ((argc != 2) && (argc != 3)) {	/* If too many or too few args, */
+    exit(LIB$_WRONUMARG);		/* ...  exit with error status  */
+  }
+
+  vms_status = SYS$TRNLNM( 0, &lnm_table, &MX_SITE_DEBUG, 0, 0);
+  if (vms_status & 1)
+    trace = 1;
+  else
+    trace = 0;
+
+  /*  Open all input files  */
+
+  tracemsg("Opening message file....");
+  vms_errchk(open_file_rms (&msgfab, &msgrab, &msgbuf, argv[1]));
+  tracemsg("Opening recipients file....");
+  vms_errchk(open_file_rms (&rcptfab, &rcptrab, &rcptbuf, argv[2]));
+
+  if (argc == 2){
+     tracemsg("Using sender address from RFC822 headers....");
+     scan_for_from_line(&msgrab, &frombuf);
+  }
+  else {
+     tracemsg("Opening sender address file....");
+     vms_errchk(open_file_rms (&fromfab, &fromrab, &frombuf, argv[3]));
+
+     tracemsg("Reading sender address from file....");
+     rms_get(&fromrab);			/* Read the from line */
+     if (!(rms_status & 1))		/* Exit if an error occurred */
+	err_exit(rms_status);
+
+     /* Set the end of the record read, then initialize the descriptor for it */
+     frombuf[fromrab.rab$w_rsz] = 0;
+
+     SYS$CLOSE(&fromfab);
+  }						/* End of "if (argc == 2)"... */
+
+  /* frombuf now has the sender's address in it */
+
+  if (strlen(frombuf) == 0) {
+	tracemsg("Unable to find sender's address, using MX%");
+	init_sdesc(&from_user, "MX%");
+  }
+  else{
+
+     /* Now add the MX% prefix and the double quotes */
+     from_line = malloc(4 + strlen(frombuf) + 1 + 1);	/* Allocate memory */
+
+     /* Make the string repliable through MX by adding MX%"" to it */
+     strcpy(from_line,"MX%\042");
+     strcat(from_line,frombuf);
+     strcat(from_line,"\042");
+     if (trace)
+	printf("MX_BULL: Sender's address is %s\n", from_line);
+     init_sdesc (&from_user, from_line);	/* Create a string descriptor */
+  }
+  /*
+    Read through all the recipients, writing the message to all BULLETIN
+    folders (identified by checking for @BULLETIN in the address).
+  */
+  rms_get(&rcptrab);				/* Read a recipient */
+  while ((rms_status & 1) & (rms_status != RMS$_EOF)){
+     tracemsg("Looking for BULLETIN folder....");
+     folder_name = &rcptbuf;			/* Point to receipt buffer */
+     if (folder_name[0] == '<'){		/* If line begins with "<" */
+	++folder_name;				/*  bump over it and check */
+	atsign = strchr(rcptbuf,'@');		/*  for a "@"		   */
+	if (atsign != 0){			/* If "@" was found,	   */
+	  if (strncmp(atsign,"@BULLETIN",9)==0){/* Is it @BULLETIN?	   */
+	    x = atsign - folder_name;		/* Length of folder name   */
+	    folder_name[x] = 0;			/* Terminate folder name   */
+	    init_sdesc (&folder, folder_name);	/* Initialize descriptor   */
+	    str$upcase(&folder, &folder);	/* Convert to uppercase    */
+	    if (trace)
+		printf("MX_BULL: Found BULLETIN folder \042%s\042....\n",
+			folder_name);
+	    tracemsg("Adding message to BULLETIN folder....");
+	    bull_status = add_to_bulletin_folder (&msgrab, &folder, &from_user);
+	    if (!(bull_status & 1)){
+		 traceerr(bull_status);
+		 vms_errchk(forward_to_postmaster(&msgrab, &folder, &from_user,
+				bull_status));
+	    }
+	    log_accounting(&folder, &from_user, bull_status);
+	    SYS$REWIND(&msgrab);	/* Rewind the file for next folder */
+
+	  }
+	}
+      }
+      rms_get(&rcptrab);		/* Read next recipient */
+  }
+
+
+  /* Close the RMS files */
+
+  SYS$CLOSE(&msgfab);  SYS$CLOSE(&rcptfab);
+
+  tracemsg("BULLETIN message processed");
+  exit(SS$_NORMAL);		/* Always return success */
+
+}
+$eod 
+$copy/log sys$input MX_BULL.TXT
+$deck
+                                    MX_BULL
+                             An MX SITE transport
+                                March 14, 1991
+
+MX_BULL is a transport between MX and BULLETIN, a VMS bulletin board program
+by Mark London at MIT.  It is designed to be called as an MX SITE transport,
+letting MX write messages into BULLETIN folders as they are processed, instead
+of routing the messages to MAIL.MAI files for each folder.
+
+The following files make up the MX_BULL distribution:
+
+   BUILD_MX_BULL.COM		Command procedure to build MX_BULL.EXE
+   MX_BULL.C			VAX C source code for MX_BULL
+   MX_BULL.TXT			This file
+   MX_BULL_SITE_DELIVER.COM	SITE_DELIVER.COM for MX_BULL
+
+The current version is 01-001.
+
+
+WHAT IS BULLETIN?
+-----------------
+BULLETIN is a VMS bulletin board written by Mark London at MIT that allows
+multiple users to access a common message base.  Messages are divided into
+folders, which work much like VMS Mail folders.  Using MX_BULL, messages can
+be routed from Internet/Bitnet mailing lists directly to BULLETIN folders,
+allowing all (or some) users on a system to access the mailing lists without
+individual subscriptions.  This can cut down on the number of incoming
+Bitnet/Internet mail messages significantly, since only one copy of a message
+need be sent to a site.
+
+BULLETIN can be found on a number of the DECUS VAX SIG tapes, including the
+Fall 1990 tapes.  It can also be retrieved by sending a mail message to
+BULLETIN@NERUS.PFC.MIT.EDU.  The body of the message must contain one of
+the following commands:
+
+        SEND ALL        Sends all bulletin files.
+        SEND filename   Sends the specified file.
+        BUGS            Sends a list of the latest bug fixes.
+        HELP or INFO    Sends a brief description of BULLETIN.
+
+
+BUILDING MX_BULL.EXE
+--------------------
+MX_BULL is written in VAX C and can be compiled by executing BUILD_MX_BULL.COM.
+
+MX_BULL must be linked with the BULLETIN object library, BULL.OLB.  The
+build procedure for MX_BULL expects the logical BULL_SOURCE to point to the
+BULLETIN library.  You must define this logical (or edit the .COM file)
+before building MX_BULL.
+
+
+INSTALLING MX_BULL
+------------------
+To install MX_BULL, perform the following steps:
+
+1.  Using MCP, define a path named BULLETIN as a SITE transport:
+
+	MCP> DEFINE PATH "BULLETIN" SITE
+
+2.  Using MCP, define a rewrite rule early in the list (this should actually
+    be done using CONFIG.MCP so that the order is correct):
+
+	MCP> DEFINE REWRITE_RULE "<{folder}@BULLETIN>" "<{folder}@BULLETIN>"
+
+3.  If you don't have a SITE transport already defined, simply copy
+    MX_BULL_SITE_DELIVER.COM to MX_EXE:SITE_DELIVER.COM.
+
+    If you do have a SITE transport defined, you'll need to merge the MX_BULL
+    stuff into the existing MX_EXE:SITE_DELIVER.COM.
+
+4.  Reset the MX routers by using MCP RESET/ALL, or shutting down MX and
+    restarting it.
+
+Once these steps have been completed, MX_BULL is set up to begin delivering
+messages to BULLETIN.
+
+
+ROUTING MESSAGES TO BULLETIN
+----------------------------
+Messages are routed to BULLETIN folders by addressing mail to
+MX%"folder@BULLETIN", where "folder" is the name of the target BULLETIN
+folder.  For example, the following commands would send a message from VMS
+Mail to the BULLETIN folder GENERAL (on the local system):
+
+	$ MAIL
+	MAIL> SEND
+	To:     MX%"GENERAL@BULLETIN"
+	Subj:   This is a test....
+	.....
+
+The message is sent to the MX router, which in turn sends it to the MX SITE
+agent, since the @BULLETIN path was defined as a SITE path.
+
+To facilitate the automatic delivery of messages to BULLETIN folders, you
+should set up forwarding addresses for each of the BULLETIN folders:
+
+	MAIL> SET FORWARD/USER=GENERAL MX%"""GENERAL@BULLETIN"""
+	MAIL> SET FORWARD/USER=MX-LIST MX%"""MX-LIST@BULLETIN"""
+
+Mail addressed to GENERAL or MX-LIST will automatically be forwarded to
+BULLETIN via MX_BULL.
+
+To subscribe to a Bitnet/Internet mailing list and have the messages delivered
+to BULLETIN, use MX's MLFAKE to send a subscription request on behalf of the
+BULLETIN folder.  For example, the user to specify would be:
+
+	MLFAKE/USER=MX-LIST ....
+
+(Alternatively, you could create a dummy account named MX-LIST (or whatever
+the list name is) that exists only long enough to send the request via MAIL.)
+
+Once added to the lists, incoming mail addressed to MX-LIST will get forwarded
+to MX%"MX-LIST@BULLETIN", which will invoke MX_BULL.  For example, an incoming
+message to my local BULLETIN folder would be addressed to:
+
+	MX-LIST@WKUVX1.bitnet
+
+Since I have MX-LIST forwarded to MX%"MX-LIST@BULLETIN", the message is routed
+to the BULLETIN folder.
+
+To try to illustrate the process, assume the node is WKUVX1.bitnet.  We've
+subscribed a fake local user, INFO-VAX, to the MX mailing list; mail forwarding
+has been set up for INFO-VAX to send it to MX%"INFO-VAX@BULLETIN".  When mail
+arrives addressed to INFO-VAX@WKUVX1.BITNET, the MX Router passes the message
+to the Local agent, which discovers that the mail is forwarded to
+MX%"INFO-VAX@BULLETIN".  The message is then sent back to the Router, which
+finds that BULLETIN is defined as a SITE path, so the message is passed to
+MX->SITE, which in turn calls MX_BULL.
+
+
+MX_BULL ACCOUNTING AND DEBUGGING
+--------------------------------
+MX_BULL accounting is enabled with the system logical MX_BULLETIN_ACCNTNG:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_ACCNTNG TRUE
+
+This will cause MX_BULL to create MX_SITE_DIR:MX_BULLETIN_ACC.DAT.  The
+logical MX_BULLETIN_ACC can be defined system-wide to change the name of the
+file:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_ACC LOCALDISK:[DIR]MX_BULL.ACCOUNTING
+
+To generate debugging logs in MX_SITE_DIR:, define the system logical
+MX_SITE_DEBUG.
+
+
+ERRORS WRITING TO BULLETIN
+--------------------------
+By default, MX_BULL_SITE_DELIVER.COM always returns success to the MX SITE
+agent.  This was done to avoid bouncing network mail back to a mailing list.
+In order to be notified in case of problems writing the message to BULLETIN,
+you can define a system logical MX_BULLETIN_POSTMASTER to be a local
+username to receive failed MX_BULL transactions:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
+
+If BULLETIN returns an error, MX_BULL will forward the message (via the
+callable VMS Mail interface) to GOATHUNTER.
+
+
+BULLETIN AND "From:" ADDRESSES
+------------------------------
+If you use the return address supplied by the MX SITE agent, the return address
+for BULLETIN messages will look something like the following:
+
+	From: MX%"@WKUVX1.BITNET:I-AMIGA@UBVM.BITNET"
+
+By default, MX_BULL_SITE_DELIVER.COM is set up to ignore the sender's address.
+If you want to use the MX SITE-supplied address, simply modify the following
+line in MX_BULL_SITE_DELIVER.COM:
+
+	$ USE_SITE_FROM = 0	!Change to 1 to use MX sender's address
+
+If the sender's address is ignored (again, the default), MX_BULL will search
+the RFC822 headers in the message for the "From:" line.  It then pulls out
+the sender's address in a format suitable for using the RESPOND command in
+BULLETIN.  This lets users easily RESPOND to the sender of a message, or
+POST a message to the list itself.
+
+Note: MX_BULL just uses the address it's given.  Some addresses are gatewayed
+to death, leaving a bad address on the "From:" line.  This frequently happens
+with messages coming via UUCP through Internet to Bitnet, etc.
+
+
+AUTHOR INFORMATION
+------------------
+MX_BULL was written by:
+
+	Hunter Goatley, VMS Systems Programmer, WKU
+
+	E-mail: goathunter@wkuvx1.bitnet
+	Voice:	502-745-5251
+
+	U.S. Mail:	Academic Computing, STH 226
+			Western Kentucky University
+			Bowling Green, KY 42101
+$eod 
+$copy/log sys$input MX_BULL_SITE_DELIVER.COM
+$deck
+$!
+$!  SITE_DELIVER.COM for MX_BULL
+$!
+$!  Author:	Hunter Goatley, goathunter@wkuvx1.bitnet
+$!  Date:	March 11, 1991
+$!
+$!  By default, MX_BULL will tell BULLETIN to search the RFC822 headers
+$!  in the message for a "Reply-to:" or "From:" line.  If you want MX_BULL
+$!  to use the P3 as the "From:" line, simply set USE_SITE_FROM to 1.
+$!
+$ USE_SITE_FROM = 0				!Change to 1 to use P3
+$ mxbull :== $mx_exe:mx_bull.exe
+$!
+$ set noon
+$ if f$trnlnm("SYS$SCRATCH").eqs."" then define SYS$SCRATCH MX_SITE_DIR:
+$ if USE_SITE_FROM				!Use P3 as "From:"?
+$ then	create mx_site_dir:sitesender.addr;	!If so, write it out to a file
+$	open/append tmp mx_site_dir:sitesender.addr;	!... to make sure DCL
+$	write tmp p3				!... doesn't mess it up
+$	close tmp				!...
+$	mxbull 'p1' 'p2' mx_site_dir:sitesender.addr
+$	delete/nolog mx_site_dir:sitesender.addr;
+$ else	mxbull 'p1' 'p2'			!Just let BULLETIN find "From:"
+$ endif
+$ exit 1	!Always return success
+$eod 
diff --git a/decus/vmslt98a/bulletin/mx.mai b/decus/vmslt98a/bulletin/mx.mai
new file mode 100755
index 0000000000000000000000000000000000000000..2631763f8654ed49f9badad0ba381715965fc2de
--- /dev/null
+++ b/decus/vmslt98a/bulletin/mx.mai
@@ -0,0 +1,958 @@
+$set nover
+$copy/log sys$input BUILD_MX_BULL.COM
+$deck
+$ save_verify = 'f$verify(0)'
+$!
+$!  Command file to build MX_BULL (MX SITE transport for BULLETIN)
+$!
+$ say := write sys$output
+$ if f$trnlnm("BULL_LIBRARY") .eqs. ""
+$ then	say "BULL_LIBRARY logical not defined; must point to BULL.OLB directory"
+$	exit
+$ endif
+$ say "Compiling MX_BULL...."
+$ cc mx_bull
+$ say "Linking MX_BULL...."
+$ link/notrace mx_bull,bull_library/LIB,SYS$SYSTEM:SYS.STB/SEL,sys$input/option
+SYS$SHARE:VAXCRTL.EXE/SHARE
+$ say "Build of MX_BULL.EXE completed"
+$ exit f$verify(save_verify).or.1
+$eod 
+$copy/log sys$input MX_BULL.C
+$deck
+#module MX_BULL "01-001"
+/*
+ *
+ *  Program:	MX_BULL
+ *
+ *  Author:	Hunter Goatley
+ *		Academic Computing, STH 226
+ *		Western Kentucky University
+ *		Bowling Green, KY 42101
+ *		goathunter@wkuvx1.bitnet
+ *		502-745-5251
+ *
+ *  Date:	March 8, 1991
+ *
+ *  Functional description:
+ *
+ *	This program serves as an MX SITE transport to transfer incoming
+ *	mail files to UALR's BULLETIN.
+ *
+ *	The MX_SITE delivery agent takes messages routed to a SITE path and
+ *	feeds them into a subprocess that executes a command procedure named
+ *	MX_EXE:SITE_DELIVER.COM.  There are three parameters passed to the
+ *	the command procedure:
+ *
+ *		P1	- The name of a temporary file containing the message
+ *			  text, including all of the RFC822 headers
+ *			  (corresponding to the DATA part of an SMTP
+ *			  transaction).
+ *		P2	- The name of a temporary file containing a list of
+ *			  a messages recipients, which corresponds to the
+ *			  RCPT_TO addresses of an SMTP transaction.
+ *		P3	- The RFC822 address of the sender of the message,
+ *			  which corresponds to the MAIL FROM address of an
+ *			  SMTP transaction.
+ *
+ *	This program expects the same parameters, except that the third
+ *	parameter is optional.  If the third parameter is omitted, BULLETIN
+ *	will scan the RFC822 headers in the message for a "From:" line.
+ *	If the third parameter is specified, it is expected to be a file
+ *	specification.  It is assumed that SITE_DELIVER.COM has written the
+ *	address to this file.
+ *
+ *	The logical MX_BULLETIN_POSTMASTER can be defined as a local
+ *	username to receive error notices.  If BULLETIN returns an error
+ *	while trying to add a message, and the MX_BULLETIN_POSTMASTER
+ *	is defined as a valid local username, the message will be mailed
+ *	to that user for further handling.
+ *
+ *	MX_BULLETIN_POSTMASTER must be defined system-wide in executive mode:
+ *
+ *		$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
+ *
+ *  Modification history:
+ *
+ *	01-001		Hunter Goatley		14-MAR-1991 14:41
+ *		Added scan_for_from_line, which scans the message's RFC822
+ *		headers for the "From:" line.  General cleanup on a few
+ *		routines.  MX_BULL now provides an RESPOND-able address in
+ *		BULLETIN.
+ *
+ *	01-000		Hunter Goatley		 8-MAR-1991 07:20
+ *		Genesis.
+ *
+ */
+
+/*  Include all needed structures and constants  */
+
+#include descrip
+#include lib$routines
+#include libdef
+#include lnmdef
+#include maildef
+#include rms
+#include ssdef
+#include str$routines
+#include string
+
+/* Declare the external BULLETIN routines that we call */
+
+unsigned long int INIT_MESSAGE_ADD();
+unsigned long int WRITE_MESSAGE_LINE();
+unsigned long int FINISH_MESSAGE_ADD();
+
+/* Define some macros to make things a little easier */
+
+#define rms_get(rab) ((rms_status = SYS$GET(rab)))
+#define err_exit(stat) {traceerr(stat); return(stat);}
+#define vms_errchk2() if(!(vms_status&1)) err_exit(vms_status);
+#define vms_errchk(func) {vms_status=func; vms_errchk2();}
+
+#define tracemsg(msg) if (trace) printf("MX_BULL: %s\n",msg);
+#define traceerr(msg) if (trace) printf("MX_BULL: Error status %%X%08x\n",msg);
+
+/* Define some global variables to make things easy */
+
+struct FAB msgfab;				/* FAB for message text */
+struct RAB msgrab;				/* RAB for message text */
+struct FAB rcptfab;				/* FAB for recipients file */
+struct RAB rcptrab;				/* RAB for recipients file */
+struct FAB fromfab;				/* FAB for FROM file */
+struct RAB fromrab;				/* RAB for FROM file */
+char msgbuf[512];				/* Input buffer for msgrab */
+char rcptbuf[512];				/* Input buffer for rcptrab */
+char frombuf[512];				/* Input buffer for frombuf */
+short trace;
+unsigned long int rms_status;			/* Status of RMS calls */
+unsigned long int vms_status;			/* Status of other calls */
+
+static $DESCRIPTOR(lnm_table,"LNM$SYSTEM_TABLE");
+
+#define itmlstend {0,0,0,0}			/* An empty item list */
+typedef struct itmlst				/* An item list structure */
+{
+  short buffer_length;
+  short item_code;
+  long buffer_address;
+  long return_length_address;
+} ITMLST;
+
+ITMLST
+  nulllist[] = {itmlstend};
+
+ITMLST
+  address_itmlst[] = {				/* MAIL$SEND_ADD_ADDRESS */
+	{0, MAIL$_SEND_USERNAME, 0, 0},
+	itmlstend},
+  bodypart_itmlst[] = {				/* MAIL$SEND_ADD_BODYPART */
+	{0, MAIL$_SEND_RECORD, 0, 0},
+	itmlstend},
+  attribute_itmlst[] = {			/* MAIL$SEND_ADD_ATTRIBUTE */
+	{0, MAIL$_SEND_TO_LINE, 0, 0},
+	{0, MAIL$_SEND_FROM_LINE, 0, 0},
+	{0, MAIL$_SEND_SUBJECT, 0, 0},
+	itmlstend}
+  ;
+
+ITMLST
+  trnlnm_itmlst[] = {				/* $TRNLNM item list */
+	{0, LNM$_STRING, 0, 0},
+	itmlstend}
+  ;
+
+
+/*
+ *
+ *  Function:	open_file_rms
+ *
+ *  Functional description:
+ *
+ *	This routine opens a sequential text file in VMS "normal text" file
+ *	format.  It uses RMS to open the file.
+ *
+ *  Inputs:
+ *
+ *	infab	- Address of the input FAB
+ *	inrab	- Address of the input RAB
+ *	buff	- Address of the input buffer
+ *	filename - Address of the filename to open (ASCIZ)
+ *
+ *  Outputs:
+ *
+ *	fab and rab are modified if file is opened.
+ *
+ *  Returns:
+ *
+ *	RMS status
+ *
+ */
+unsigned long int
+open_file_rms (struct FAB *infab, struct RAB *inrab, char *buff, char *filename)
+{
+    unsigned long int rms_status;
+
+    *infab = cc$rms_fab;			/* Initialize the FAB */
+    *inrab = cc$rms_rab;			/* Initialize the RAB */
+    infab->fab$b_fns = strlen(filename);	/* Set filename length */
+    infab->fab$l_fna = filename;		/* Set filename address */
+    infab->fab$b_fac = FAB$M_GET;		/* GET access only */
+    infab->fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
+    inrab->rab$l_fab = infab;			/* Let RAB point to FAB */
+    inrab->rab$b_rac = RAB$C_SEQ;		/* Sequential file access */
+    inrab->rab$w_usz = 512;			/* Record size is 512 bytes */
+    inrab->rab$l_ubf = buff;			/* Read to this buffer */
+
+    rms_status = SYS$OPEN (infab);		/* Open the file */
+    if (!(rms_status & 1))			/* If an error occurs, return */
+	return (rms_status);			/* ... a status */
+    rms_status = SYS$CONNECT (inrab);		/* Connect the RAB */
+    return (rms_status);			/* Return the RMS status */
+}
+
+/*
+ *
+ *  Function:	init_sdesc
+ *
+ *  Functional description:
+ *
+ *	Initialize a static string descriptor.
+ *
+ *  Inputs:
+ *
+ *	sdesc	- Address of the descriptor to initialize
+ *		  (of type struct dsc$descriptor_s)
+ *	string	- Address of null-terminated string the descriptor describes
+ *
+ *  Outputs:
+ *
+ *	sdesc	- Descriptor passed as sdesc is initialized
+ *
+ */
+void
+init_sdesc (struct dsc$descriptor_s *sdesc, char *string)
+{
+    sdesc->dsc$w_length = strlen(string);	/* Set the length	*/
+    sdesc->dsc$b_dtype = DSC$K_DTYPE_T;		/* Type is text		*/
+    sdesc->dsc$b_class = DSC$K_CLASS_S;		/* Class is static	*/
+    sdesc->dsc$a_pointer = string;		/* Point to the string	*/
+}
+
+/*
+ *
+ *  Function:	add_to_bulletin_folder
+ *
+ *  Functional description:
+ *
+ *	Adds a message to a BULLETIN folder by calling the external
+ *	BULLETIN routines INIT_MESSAGE_ADD, WRITE_MESSAGE_LINE, and
+ *	FINISH_MESSAGE_ADD.
+ *
+ *	The following constants are (may be) passed to INIT_MESSAGE_ADD:
+ *
+ *		Subject = "" 	Causes BULLETIN to scan RFC822 headers for
+ *				a "Subject:" or "Subj:" line
+ *		From = "MX%"	Causes BULLETIN to scan RFC822 headers for
+ *				a "Reply-to:" or "From:" line
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - RMS status of call to INIT_MESSAGE_ADD
+ *
+ */
+unsigned long int
+add_to_bulletin_folder(struct RAB *filerab, void *folder, void *from)
+{
+    unsigned long int bull_status;	/* Status from INIT_MESSAGE_ADD */
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    static $DESCRIPTOR(subject,"");	/* Subject is "" */
+
+    /* Call BULLETIN routine to initialize adding the message */
+
+    INIT_MESSAGE_ADD (folder, from, &subject, &bull_status);
+
+    if (!(bull_status & 1)){					/* Error? */
+	return(bull_status);
+    }
+
+    /*	Loop reading message lines until end-of-file.  For each line read,
+	create a string descriptor for it and call the BULLETIN routine to
+	add the line. */
+
+    while (rms_get(filerab) != RMS$_EOF){		/* Loop until EOF */
+	filerab->rab$l_rbf[filerab->rab$w_rsz] = 0;	/* End byte = NULL */
+	init_sdesc(&msg_line, filerab->rab$l_rbf);	/* Now build desc. */
+	WRITE_MESSAGE_LINE (&msg_line);			/* Add to BULLETIN */
+    }
+
+    FINISH_MESSAGE_ADD();		/* Call BULLETIN routine to finish */
+
+    tracemsg("Message added to folder");
+    return(SS$_NORMAL);			/* Return success to caller */
+}
+
+
+/*
+ *
+ *  Function:	scan_for_from_line
+ *
+ *  Functional description:
+ *
+ *	The routine scans the message's RFC822 headers for the "From:" line.
+ *	It parses out the address by extracting the <address>.
+ *
+ *	This routine was necessary because letting BULLETIN find the "From:"
+ *	line was resulting in a non-RESPONDable address for MX.  For example,
+ *	BULLETIN was creating:
+ *
+ *		From: MX%"Hunter Goatley, WKU <goathunter@WKUVX1.BITNET>"
+ *
+ *	but MX needs
+ *
+ *		From: MX%"<goathunter@WKUVX1.BITNET>"
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *
+ *  Outputs:
+ *
+ *	final_from - Address of a character buffer to receive the final address
+ *
+ *  Returns:
+ *
+ *	unsigned long int - binary success/failure status
+ *
+ *  Side effects:
+ *
+ *	The message file is rewound so that subsequent GETs start at the
+ *	beginning of the message.
+ *
+ */
+unsigned long int
+scan_for_from_line(struct RAB *filerab, char *final_from)
+{
+    unsigned long int scan_status;	/* Status from INIT_MESSAGE_ADD */
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    char whole_from_line[512];		/* The assembled "From:" line */
+    char *filebuffer;			/* Pointer to the input buffer */
+    int i, j, x;			/* Work variables */
+
+    scan_status = SS$_NORMAL;			/* Assume success */
+    whole_from_line[0] = '\0';			/* Initialize work buffer */
+
+    /*	Loop reading message lines until end-of-file or first null line,
+	which should signal the end of the RFC822 header.  For each line read,
+	check to see if we've located the "From:" line.
+    */
+
+    filebuffer = filerab->rab$l_ubf;			/* Init buffer ptr */
+    while ((rms_get(filerab) != RMS$_EOF) &&		/* Loop until EOF */
+	   ((x = filerab->rab$w_rsz) != 0)){		/* or null record */
+	filebuffer[x] = '\0';				/* Set NULL byte */
+	if (strncmp(filebuffer,"From:",5)==0){		/* Is it the "From:"? */
+
+	   /* Found "From:" line */
+	   tracemsg("Found \042From:\042 line in RFC822 header");
+	   strcpy(whole_from_line,filebuffer);		/* Copy to work buff */
+
+	   /* The "From:" line may actually be split over several lines.
+	      In such cases, the remaining lines are indented by 6 spaces.
+	      To handle this, loop reading records until one is read that
+	      doesn't begin with a blank.  As each record is read, it is
+	      trimmed and tacked on to whole_from_line, so we end up with
+	      the entire "From:" line in one buffer.  */
+
+	   while((rms_get(filerab) != RMS$_EOF) &&	/* Read rest of From: */
+		 (filebuffer[0] == ' ')){		/* ... line */
+	      for (i = 0; filebuffer[i] == ' '; ++i);	/* Step over blanks */
+	      strcat(whole_from_line,&filebuffer[i]);	/* Tack it on end */
+	   }
+
+	   /* Now have the whole "From:" line in whole_from_line.  Since
+	      the real address is enclosed in "<>", look for it by
+	      searching for the last "<" and reading up to the ">".  */
+
+	   i = strrchr(whole_from_line,'<');		/* Find last "<" */
+	   if (i != 0){					/* Found it.... */
+		j = strchr(i,'>');			/* Find last ">" */
+	        j = j-i+1;				/* Calc addr length */
+	   }
+	   else{
+		j = strlen(whole_from_line)-6;		/* Don't count From: */
+		i = &whole_from_line + 6;		/* in string length */
+	   }
+	   if (j < 0){					/* If neg., error */
+		tracemsg("Error - unable to locate from address");
+		strcpy(final_from,"");			/* Return null string */
+		scan_status = 0;			/* Set error status */
+	   }
+	   else {
+		tracemsg("Found sender's address in RFC822 header");
+		strncpy(final_from, i, j);		/* Copy to caller */
+	   }	
+	}
+    }
+
+    SYS$REWIND(filerab);		/* Rewind the file to the beginning */
+    return(scan_status);		/* Return success to caller */
+}
+
+
+/*
+ *
+ *  Function:	forward_to_postmaster
+ *
+ *  Functional description:
+ *
+ *	If an error occurs trying to write a message to a BULLETIN folder,
+ *	this routine is called to forward the message to the local
+ *	postmaster.
+ *
+ *  Inputs:
+ *
+ *	filerab	- Address of the message file's RAB
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *	status	- Address of longword containing the BULLETIN error code
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - binary status of call to INIT_MESSAGE_ADD
+ *
+ *  Side effects:
+ *
+ *	The message file is rewound so that subsequent calls to this routine
+ *	can be made (in case the message is to be written to several folders).
+ *
+ */
+unsigned long int
+forward_to_postmaster(struct RAB *filerab, void *folder, void *from, int status)
+{
+    struct dsc$descriptor_s msg_line;	/* Descriptor for a line of the msg */
+    struct dsc$descriptor_s subject;
+    char subject_buf[256];
+    char postmaster[256];   int postmaster_len;
+    char status_msg_buf[256];   int status_msg_len;
+    struct dsc$descriptor_s status_msg;
+    static $DESCRIPTOR(faostr,"Failed BULLETIN message for folder !AS");
+    static $DESCRIPTOR(MXBULL,"MX->SITE (BULLETIN delivery)");
+    static $DESCRIPTOR(postmaster_lnm,"MX_BULLETIN_POSTMASTER");
+    int send_context = 0;  int x;  int y;
+
+    static char *error_msgs[] = {
+	{"Error delivering message to BULLETIN folder.  BULLETIN error status:"},
+	{""},
+	{""},
+	{"Original message text follows:"},
+	{"--------------------------------------------------"}
+    };
+
+    trnlnm_itmlst[0].buffer_length = 255;
+    trnlnm_itmlst[0].buffer_address = &postmaster;
+    trnlnm_itmlst[0].return_length_address = &postmaster_len;
+
+    SYS$TRNLNM( 0, &lnm_table, &postmaster_lnm, 0, trnlnm_itmlst);
+    if (postmaster_len == 0)		/* If logical is not defined, */
+	return(SS$_NORMAL);		/* then pretend it worked     */
+
+    tracemsg("Forwarding message to local postmaster....");
+    subject.dsc$w_length = 255;
+    subject.dsc$a_pointer = &subject_buf;
+    SYS$FAO(&faostr, &subject, &subject, folder);	/* Format the subject */
+
+    address_itmlst[0].buffer_length = postmaster_len;		   /* To: */
+    address_itmlst[0].buffer_address = &postmaster;		   /* To: */
+    attribute_itmlst[0].buffer_length = postmaster_len;		   /* To: */
+    attribute_itmlst[0].buffer_address = &postmaster;		   /* To: */
+    attribute_itmlst[1].buffer_length = MXBULL.dsc$w_length;	   /* From: */
+    attribute_itmlst[1].buffer_address = MXBULL.dsc$a_pointer;	   /* From: */
+    attribute_itmlst[2].buffer_length = subject.dsc$w_length;	   /* Subject:*/
+    attribute_itmlst[2].buffer_address = subject.dsc$a_pointer;	   /* Subject:*/
+
+    vms_errchk(mail$send_begin(&send_context, &nulllist, &nulllist));
+    vms_errchk(mail$send_add_address(&send_context, &address_itmlst,
+			&nulllist));
+    vms_errchk(mail$send_add_attribute(&send_context, &attribute_itmlst,
+			&nulllist));
+
+    for (x = 0; x < 5; x++){
+	bodypart_itmlst[0].buffer_length = strlen(error_msgs[x]);
+	bodypart_itmlst[0].buffer_address = error_msgs[x];
+	vms_errchk(mail$send_add_bodypart(&send_context,
+		&bodypart_itmlst, &nulllist));
+	if (x == 1){
+	  status_msg.dsc$w_length = 256;
+	  status_msg.dsc$b_dtype = DSC$K_DTYPE_T;
+	  status_msg.dsc$b_class = DSC$K_CLASS_S;
+	  status_msg.dsc$a_pointer = &status_msg_buf;
+	  y = SYS$GETMSG (status, &status_msg, &status_msg, 15, 0);
+	  if (!(y & 1))
+	     sprintf(status_msg_buf,"Error code is %%X%08x",status);
+	  else
+	     status_msg_buf[status_msg.dsc$w_length] = '\0';
+	  bodypart_itmlst[0].buffer_length = strlen(status_msg_buf);
+	  bodypart_itmlst[0].buffer_address = &status_msg_buf;
+	  vms_errchk(mail$send_add_bodypart(&send_context,&bodypart_itmlst,
+		&nulllist));
+	}
+    }
+
+    while (rms_get(filerab) != RMS$_EOF){		/* Loop until EOF */
+	bodypart_itmlst[0].buffer_length = filerab->rab$w_rsz;
+	bodypart_itmlst[0].buffer_address = filerab->rab$l_rbf;
+	vms_errchk(mail$send_add_bodypart(&send_context,
+		&bodypart_itmlst, &nulllist));
+    }
+
+    vms_errchk(mail$send_message(&send_context, &nulllist, &nulllist));
+    vms_errchk(mail$send_end(&send_context, &nulllist, &nulllist));
+
+    tracemsg("Message forwarded to postmaster....");
+}
+
+
+/*
+ *
+ *  Function:	log_accounting
+ *
+ *  Functional description:
+ *
+ *	This routine will write an accounting record for the message.
+ *
+ *  Inputs:
+ *
+ *	folder	- Address of a string descriptor for the name of the folder
+ *	from	- Address of a string descriptor for the "From:" address
+ *	status	- Address of longword containing the BULLETIN error code
+ *
+ *  Outputs:
+ *
+ *	None.
+ *
+ *  Returns:
+ *
+ *	unsigned long int - RMS status
+ *
+ */
+unsigned long int
+log_accounting(void *folder, void *from, int bull_status)
+{
+    struct FAB accfab;
+    struct RAB accrab;
+    static $DESCRIPTOR(MX_BULL_ACCNTNG,"MX_BULLETIN_ACCNTNG");
+    static $DESCRIPTOR(faostr,
+	"!%D MX_BULL: FOLDER=\042!AS\042, ORIGIN=\042!AS\042, STATUS=%X!XL");
+    char outbufbuf[256];
+    struct dsc$descriptor_s outbuf = {256, DSC$K_DTYPE_T, DSC$K_CLASS_S,
+		 &outbufbuf};
+
+    int status;
+    static char bullacc[] = "MX_BULLETIN_ACC";
+    static char bullaccdef[] = "MX_SITE_DIR:.DAT";
+
+    status = SYS$TRNLNM( 0, &lnm_table, &MX_BULL_ACCNTNG, 0, 0);
+    if (!(status & 1))
+	return(SS$_NORMAL);
+
+    tracemsg("Writing accounting information to accounting log....");
+    accfab = cc$rms_fab;
+    accrab = cc$rms_rab;
+    accfab.fab$b_fns = strlen(bullacc);		/* Set filename length */
+    accfab.fab$l_fna = &bullacc;		/* Set filename address */
+    accfab.fab$b_dns = strlen(bullaccdef);	/* Set filename length */
+    accfab.fab$l_dna = &bullaccdef;		/* Set filename address */
+    accfab.fab$b_fac = FAB$M_PUT;		/* PUT access only */
+    accfab.fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
+    accfab.fab$b_rfm = FAB$C_VAR;		/* Variable length records */
+    accfab.fab$b_rat = FAB$M_CR;		/* Normal "text" rat */
+    accrab.rab$l_fab = &accfab;			/* Let RAB point to FAB */
+    accrab.rab$b_rac = RAB$C_SEQ;		/* Sequential file access */
+
+    status = SYS$OPEN (&accfab);		/* Try to open the file */
+    if (status & 1)				/* Success? */
+	accrab.rab$l_rop = RAB$M_EOF;		/* Set to EOF */
+    else					/* Couldn't open, so create */
+	status = SYS$CREATE (&accfab);		/* ... a new one */
+    if (status & 1){				/* If either was OK... */
+	status = SYS$CONNECT (&accrab);		/* Connect the RAB */
+	if (status == RMS$_EOF)			/* RMS$_EOF status is OK */
+	   status = RMS$_NORMAL;		/* Change it to NORMAL */
+	if (!(status & 1)){			/* If any error occurred */
+	   tracemsg("Unable to open accounting file");
+	   traceerr(status);
+	   SYS$CLOSE (&accfab);			/* Close the file */
+	   return(status);			/* And return the error */
+	}
+    }
+    else
+	return(status);
+
+    SYS$FAO(&faostr, &outbuf, &outbuf, 0, folder, from, bull_status);
+    accrab.rab$w_rsz = outbuf.dsc$w_length;
+    accrab.rab$l_rbf = outbuf.dsc$a_pointer;
+    SYS$PUT (&accrab);
+    SYS$CLOSE (&accfab);
+}
+
+/*
+ * 
+ *  Main routine
+ *
+ */
+main(int argc, char *argv[])
+{
+  struct dsc$descriptor_s folder;	/* Descriptor for the folder name */
+  struct dsc$descriptor_s from_user;	/* Descriptor for "From:" line */
+  static $DESCRIPTOR(MX_SITE_DEBUG,"MX_SITE_DEBUG");
+
+  char *from_line;			/* Pointer to dynamic "From:" buffer */
+  char *folder_name;			/* Pointer to folder name in rcptbuf */
+  char *atsign;				/* Pointer to "@" in rcptbuf */
+  int  x;				/* Work variable */
+  unsigned long int bull_status;	/* Status from add_to_bulletin_folder */
+
+  --argc;				/* Don't count the program name */
+  if ((argc != 2) && (argc != 3)) {	/* If too many or too few args, */
+    exit(LIB$_WRONUMARG);		/* ...  exit with error status  */
+  }
+
+  vms_status = SYS$TRNLNM( 0, &lnm_table, &MX_SITE_DEBUG, 0, 0);
+  if (vms_status & 1)
+    trace = 1;
+  else
+    trace = 0;
+
+  /*  Open all input files  */
+
+  tracemsg("Opening message file....");
+  vms_errchk(open_file_rms (&msgfab, &msgrab, &msgbuf, argv[1]));
+  tracemsg("Opening recipients file....");
+  vms_errchk(open_file_rms (&rcptfab, &rcptrab, &rcptbuf, argv[2]));
+
+  if (argc == 2){
+     tracemsg("Using sender address from RFC822 headers....");
+     scan_for_from_line(&msgrab, &frombuf);
+  }
+  else {
+     tracemsg("Opening sender address file....");
+     vms_errchk(open_file_rms (&fromfab, &fromrab, &frombuf, argv[3]));
+
+     tracemsg("Reading sender address from file....");
+     rms_get(&fromrab);			/* Read the from line */
+     if (!(rms_status & 1))		/* Exit if an error occurred */
+	err_exit(rms_status);
+
+     /* Set the end of the record read, then initialize the descriptor for it */
+     frombuf[fromrab.rab$w_rsz] = 0;
+
+     SYS$CLOSE(&fromfab);
+  }						/* End of "if (argc == 2)"... */
+
+  /* frombuf now has the sender's address in it */
+
+  if (strlen(frombuf) == 0) {
+	tracemsg("Unable to find sender's address, using MX%");
+	init_sdesc(&from_user, "MX%");
+  }
+  else{
+
+     /* Now add the MX% prefix and the double quotes */
+     from_line = malloc(4 + strlen(frombuf) + 1 + 1);	/* Allocate memory */
+
+     /* Make the string repliable through MX by adding MX%"" to it */
+     strcpy(from_line,"MX%\042");
+     strcat(from_line,frombuf);
+     strcat(from_line,"\042");
+     if (trace)
+	printf("MX_BULL: Sender's address is %s\n", from_line);
+     init_sdesc (&from_user, from_line);	/* Create a string descriptor */
+  }
+  /*
+    Read through all the recipients, writing the message to all BULLETIN
+    folders (identified by checking for @BULLETIN in the address).
+  */
+  rms_get(&rcptrab);				/* Read a recipient */
+  while ((rms_status & 1) & (rms_status != RMS$_EOF)){
+     tracemsg("Looking for BULLETIN folder....");
+     folder_name = &rcptbuf;			/* Point to receipt buffer */
+     if (folder_name[0] == '<'){		/* If line begins with "<" */
+	++folder_name;				/*  bump over it and check */
+	atsign = strchr(rcptbuf,'@');		/*  for a "@"		   */
+	if (atsign != 0){			/* If "@" was found,	   */
+	  if (strncmp(atsign,"@BULLETIN",9)==0){/* Is it @BULLETIN?	   */
+	    x = atsign - folder_name;		/* Length of folder name   */
+	    folder_name[x] = 0;			/* Terminate folder name   */
+	    init_sdesc (&folder, folder_name);	/* Initialize descriptor   */
+	    str$upcase(&folder, &folder);	/* Convert to uppercase    */
+	    if (trace)
+		printf("MX_BULL: Found BULLETIN folder \042%s\042....\n",
+			folder_name);
+	    tracemsg("Adding message to BULLETIN folder....");
+	    bull_status = add_to_bulletin_folder (&msgrab, &folder, &from_user);
+	    if (!(bull_status & 1)){
+		 traceerr(bull_status);
+		 vms_errchk(forward_to_postmaster(&msgrab, &folder, &from_user,
+				bull_status));
+	    }
+	    log_accounting(&folder, &from_user, bull_status);
+	    SYS$REWIND(&msgrab);	/* Rewind the file for next folder */
+
+	  }
+	}
+      }
+      rms_get(&rcptrab);		/* Read next recipient */
+  }
+
+
+  /* Close the RMS files */
+
+  SYS$CLOSE(&msgfab);  SYS$CLOSE(&rcptfab);
+
+  tracemsg("BULLETIN message processed");
+  exit(SS$_NORMAL);		/* Always return success */
+
+}
+$eod 
+$copy/log sys$input MX_BULL.TXT
+$deck
+                                    MX_BULL
+                             An MX SITE transport
+                                March 14, 1991
+
+MX_BULL is a transport between MX and BULLETIN, a VMS bulletin board program
+by Mark London at MIT.  It is designed to be called as an MX SITE transport,
+letting MX write messages into BULLETIN folders as they are processed, instead
+of routing the messages to MAIL.MAI files for each folder.
+
+The following files make up the MX_BULL distribution:
+
+   BUILD_MX_BULL.COM		Command procedure to build MX_BULL.EXE
+   MX_BULL.C			VAX C source code for MX_BULL
+   MX_BULL.TXT			This file
+   MX_BULL_SITE_DELIVER.COM	SITE_DELIVER.COM for MX_BULL
+
+The current version is 01-001.
+
+
+WHAT IS BULLETIN?
+-----------------
+BULLETIN is a VMS bulletin board written by Mark London at MIT that allows
+multiple users to access a common message base.  Messages are divided into
+folders, which work much like VMS Mail folders.  Using MX_BULL, messages can
+be routed from Internet/Bitnet mailing lists directly to BULLETIN folders,
+allowing all (or some) users on a system to access the mailing lists without
+individual subscriptions.  This can cut down on the number of incoming
+Bitnet/Internet mail messages significantly, since only one copy of a message
+need be sent to a site.
+
+BULLETIN can be found on a number of the DECUS VAX SIG tapes, including the
+Fall 1990 tapes.  It can also be retrieved by sending a mail message to
+BULLETIN@NERUS.PFC.MIT.EDU.  The body of the message must contain one of
+the following commands:
+
+        SEND ALL        Sends all bulletin files.
+        SEND filename   Sends the specified file.
+        BUGS            Sends a list of the latest bug fixes.
+        HELP or INFO    Sends a brief description of BULLETIN.
+
+
+BUILDING MX_BULL.EXE
+--------------------
+MX_BULL is written in VAX C and can be compiled by executing BUILD_MX_BULL.COM.
+
+MX_BULL must be linked with the BULLETIN object library, BULL.OLB.  The
+build procedure for MX_BULL expects the logical BULL_LIBRARY to point to the
+BULLETIN library.  You must define this logical (or edit the .COM file)
+before building MX_BULL.
+
+
+INSTALLING MX_BULL
+------------------
+To install MX_BULL, perform the following steps:
+
+1.  Using MCP, define a path named BULLETIN as a SITE transport:
+
+	MCP> DEFINE PATH "BULLETIN" SITE
+
+2.  Using MCP, define a rewrite rule early in the list (this should actually
+    be done using CONFIG.MCP so that the order is correct):
+
+	MCP> DEFINE REWRITE_RULE "<{folder}@BULLETIN>" "<{folder}@BULLETIN>"
+
+3.  If you don't have a SITE transport already defined, simply copy
+    MX_BULL_SITE_DELIVER.COM to MX_EXE:SITE_DELIVER.COM.
+
+    If you do have a SITE transport defined, you'll need to merge the MX_BULL
+    stuff into the existing MX_EXE:SITE_DELIVER.COM.
+
+4.  Reset the MX routers by using MCP RESET/ALL, or shutting down MX and
+    restarting it.
+
+Once these steps have been completed, MX_BULL is set up to begin delivering
+messages to BULLETIN.
+
+
+ROUTING MESSAGES TO BULLETIN
+----------------------------
+Messages are routed to BULLETIN folders by addressing mail to
+MX%"folder@BULLETIN", where "folder" is the name of the target BULLETIN
+folder.  For example, the following commands would send a message from VMS
+Mail to the BULLETIN folder GENERAL (on the local system):
+
+	$ MAIL
+	MAIL> SEND
+	To:     MX%"GENERAL@BULLETIN"
+	Subj:   This is a test....
+	.....
+
+The message is sent to the MX router, which in turn sends it to the MX SITE
+agent, since the @BULLETIN path was defined as a SITE path.
+
+To facilitate the automatic delivery of messages to BULLETIN folders, you
+should set up forwarding addresses for each of the BULLETIN folders:
+
+	MAIL> SET FORWARD/USER=GENERAL MX%"""GENERAL@BULLETIN"""
+	MAIL> SET FORWARD/USER=MX-LIST MX%"""MX-LIST@BULLETIN"""
+
+Mail addressed to GENERAL or MX-LIST will automatically be forwarded to
+BULLETIN via MX_BULL.
+
+To subscribe to a Bitnet/Internet mailing list and have the messages delivered
+to BULLETIN, use MX's MLFAKE to send a subscription request on behalf of the
+BULLETIN folder.  For example, the user to specify would be:
+
+	MLFAKE/USER=MX-LIST ....
+
+(Alternatively, you could create a dummy account named MX-LIST (or whatever
+the list name is) that exists only long enough to send the request via MAIL.)
+
+Once added to the lists, incoming mail addressed to MX-LIST will get forwarded
+to MX%"MX-LIST@BULLETIN", which will invoke MX_BULL.  For example, an incoming
+message to my local BULLETIN folder would be addressed to:
+
+	MX-LIST@WKUVX1.bitnet
+
+Since I have MX-LIST forwarded to MX%"MX-LIST@BULLETIN", the message is routed
+to the BULLETIN folder.
+
+To try to illustrate the process, assume the node is WKUVX1.bitnet.  We've
+subscribed a fake local user, INFO-VAX, to the MX mailing list; mail forwarding
+has been set up for INFO-VAX to send it to MX%"INFO-VAX@BULLETIN".  When mail
+arrives addressed to INFO-VAX@WKUVX1.BITNET, the MX Router passes the message
+to the Local agent, which discovers that the mail is forwarded to
+MX%"INFO-VAX@BULLETIN".  The message is then sent back to the Router, which
+finds that BULLETIN is defined as a SITE path, so the message is passed to
+MX->SITE, which in turn calls MX_BULL.
+
+
+MX_BULL ACCOUNTING AND DEBUGGING
+--------------------------------
+MX_BULL accounting is enabled with the system logical MX_BULLETIN_ACCNTNG:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_ACCNTNG TRUE
+
+This will cause MX_BULL to create MX_SITE_DIR:MX_BULLETIN_ACC.DAT.  The
+logical MX_BULLETIN_ACC can be defined system-wide to change the name of the
+file:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_ACC LOCALDISK:[DIR]MX_BULL.ACCOUNTING
+
+To generate debugging logs in MX_SITE_DIR:, define the system logical
+MX_SITE_DEBUG.
+
+
+ERRORS WRITING TO BULLETIN
+--------------------------
+By default, MX_BULL_SITE_DELIVER.COM always returns success to the MX SITE
+agent.  This was done to avoid bouncing network mail back to a mailing list.
+In order to be notified in case of problems writing the message to BULLETIN,
+you can define a system logical MX_BULLETIN_POSTMASTER to be a local
+username to receive failed MX_BULL transactions:
+
+	$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
+
+If BULLETIN returns an error, MX_BULL will forward the message (via the
+callable VMS Mail interface) to GOATHUNTER.
+
+
+BULLETIN AND "From:" ADDRESSES
+------------------------------
+If you use the return address supplied by the MX SITE agent, the return address
+for BULLETIN messages will look something like the following:
+
+	From: MX%"@WKUVX1.BITNET:I-AMIGA@UBVM.BITNET"
+
+By default, MX_BULL_SITE_DELIVER.COM is set up to ignore the sender's address.
+If you want to use the MX SITE-supplied address, simply modify the following
+line in MX_BULL_SITE_DELIVER.COM:
+
+	$ USE_SITE_FROM = 0	!Change to 1 to use MX sender's address
+
+If the sender's address is ignored (again, the default), MX_BULL will search
+the RFC822 headers in the message for the "From:" line.  It then pulls out
+the sender's address in a format suitable for using the RESPOND command in
+BULLETIN.  This lets users easily RESPOND to the sender of a message, or
+POST a message to the list itself.
+
+Note: MX_BULL just uses the address it's given.  Some addresses are gatewayed
+to death, leaving a bad address on the "From:" line.  This frequently happens
+with messages coming via UUCP through Internet to Bitnet, etc.
+
+
+AUTHOR INFORMATION
+------------------
+MX_BULL was written by:
+
+	Hunter Goatley, VMS Systems Programmer, WKU
+
+	E-mail: goathunter@wkuvx1.bitnet
+	Voice:	502-745-5251
+
+	U.S. Mail:	Academic Computing, STH 226
+			Western Kentucky University
+			Bowling Green, KY 42101
+$eod 
+$copy/log sys$input MX_BULL_SITE_DELIVER.COM
+$deck
+$!
+$!  SITE_DELIVER.COM for MX_BULL
+$!
+$!  Author:	Hunter Goatley, goathunter@wkuvx1.bitnet
+$!  Date:	March 11, 1991
+$!
+$!  By default, MX_BULL will tell BULLETIN to search the RFC822 headers
+$!  in the message for a "Reply-to:" or "From:" line.  If you want MX_BULL
+$!  to use the P4 as the "From:" line, simply set USE_SITE_FROM to 1.
+$!
+$ USE_SITE_FROM = 0				!Change to 1 to use P4
+$ mxbull :== $mx_exe:mx_bull.exe
+$!
+$ set noon
+$ if f$trnlnm("SYS$SCRATCH").eqs."" then define SYS$SCRATCH MX_SITE_DIR:
+$ if USE_SITE_FROM				!Use P4 as "From:"?
+$ then	create mx_site_dir:sitesender.addr;	!If so, write it out to a file
+$	open/append tmp mx_site_dir:sitesender.addr;	!... to make sure DCL
+$	write tmp p4				!... doesn't mess it up
+$	close tmp				!...
+$	mxbull 'p2' 'p3' mx_site_dir:sitesender.addr
+$	delete/nolog mx_site_dir:sitesender.addr;
+$ else	mxbull 'p2' 'p3'			!Just let BULLETIN find "From:"
+$ endif
+$ exit 1	!Always return success
+$eod 
diff --git a/decus/vmslt98a/bulletin/news.alt b/decus/vmslt98a/bulletin/news.alt
new file mode 100755
index 0000000000000000000000000000000000000000..1f6de96775944ed442843d5172344f89db0fe573
--- /dev/null
+++ b/decus/vmslt98a/bulletin/news.alt
@@ -0,0 +1,254 @@
+
+From: ccs@aber.ac.uk (Christopher Samuel)
+Date:  2-OCT-1992  11:36:37
+Description: Creating a new "alt" group -- guidelines
+
+Archive-name: alt-config-guide
+Version: 1.2
+Last-modified: Wed Sep  2 16:31:55 GMT 1992
+ 
+ 
+ 
+		Guidelines for the creation of an "alt" group.
+ 
+There are no rules or guidelines for creation of "alt" groups, However
+there does appear to be an established procedure which follows.  First a
+quick bit of common-sense on choosing the name:
+ 
+When choosing a name for a group please note the only commandment: Thou
+shalt not choose a group name which may cause network harm or harm to a
+local machine. 
+ 
+          Examples:
+ 
+          alt.fan.enya.puke.puke.pukeSender:
+ 
+          [preceding line to Sender had <CR> deleted; also the
+           trailing : can cause problems in some news systems]
+ 
+          alt.verylonggroupnamethathasadirectorylongerthanmost\
+          machinessupportsotherehaha.very.funny
+ 
+          alt.[insert300charactershere].very.long.group.name.\
+          that.is.too.big.for.newsrc
+ 
+          alt.*.this.name.has.bad.characters.in.it
+ 
+          alt..double.dot.group.name
+ 
+ 
+		Now the Guidelines:
+		-------------------
+ 
+       1) Propose a new alt group in alt.config.  The proposal
+          should include a charter or purpose for the new group, and
+          some demonstration of the need for the group.  It is best to
+          make it clear in your subject line that you are proposing a
+          new group. Be prepared to explain why an existing group cannot
+          be used for this purpose, and why the group should be in "alt"
+          rather than in one of the mainstream hierarchies (like
+          "rec", "sci", etc.).  Avoiding the complexity of the
+          mainstream group creation procedure is not a very good
+          reason, groups should not be created in "alt" just because
+          it's easier.  Don't forget that mainstream groups can also
+          be created by the "trial" mechanism.  Many sites do not get
+          any alt groups, so if you are proposing a serious group, it
+          is worth the effort to try to get it into a mainstream
+          hierarchy.
+ 
+       2) See what the alt.net.opinion of the new group is.  Wait a
+          few days for replies to trickle in from the far corners of
+          the net.  If the consensus (however you determine that) is
+          that the group should be created, then proceed to step 3.
+ 
+          (these first two steps are often ignored, which usually
+          leads to unpleasantness in step 4 below)
+ 
+       3) Post a "newgroup" control message.  If you don't know
+          how to do this, check with your news administrator.  If you
+          ARE your news administrator, and you can't figure it out
+          from the documentation you have (or don't have any
+          documentation) send me mail and I will help you.  NOTE that
+          many sites do NOT automatically honor "newgroup" and
+          "rmgroup" control messages, the news software at these sites
+          will send mail to the news administrator, who will evaluate
+          your request and decide whether or not to create the group.
+          It may take a couple of days for the control message to
+          propagate and be acted upon, so don't expect instant
+          availability of the new group, particularly if you post the
+          control message on a Friday night.
+ 
+          NB:	It is good manners to put a description of the new
+          	newsgroup into the newgroup message, along with a
+          	one-line description suitable for inclusion into the
+          	newsgroups file.
+ 
+       4) Let the individual site news administrators decide
+          whether to honor your "newgroup" message.  Most admins
+          prefer that the message come from a verifiable account,
+          messages which are obviously forged, or have not been
+          discussed in alt.config and contain no explanation will
+          probably not be honored by many sites.  Persons opposed to
+          the group, or admins who feel that the newgroup message was
+          a forgery may send out "rmgroup" messages to try to sabotage
+          the group.  It may take several iterations of this process
+          to firmly establish the new group.  It has been humorously
+          suggested that only alt groups which get 100 more "newgroup"
+          than "rmgroup" messages should be established.  However,
+          these "rmgroup wars" are annoying to news administrators,
+          and reduce the overall acceptance (and distribution) of the
+          "alt" hierarchy.  This is the reason that steps 1 and 2
+          above are important.
+ 
+ 
+This may sound like a lot of rigamarole, and it is.  The purpose is to
+discourage creation of alt groups that might be better off as mainstream
+groups, or that might be better of left uncreated.
+ 
+Don't take this all too seriously, though.  The "alt" net is the last
+remaining refuge away from the control freaks, namespace purists and
+net.cops (like myself) that maintain and enforce the mainstream
+newsgroup guidelines.
+ 
+There is still some room for spontaneity out here on the "alt" frontier. 
+Successful groups have been created without following these suggestions. 
+Almost any non-forged, serious newgroup message will at least be
+considered by most news admins.  Some groups have been created just on a
+whim.  The concept behind the group better be good (or a least
+entertaining), though!
+ 
+[ If you want more information on mainstream group creation see the post
+  "How to Create a New Newsgroup" posted to news.answers, news.admin and
+  news.groups. ]
+ 
+-- 
+ Christopher Samuel, c/o Computer Unit, UCW Aberystwyth, Aberystwyth, WALES
+  RFC: ccs@aber.ac.uk   UUCP: *!mcsun!uknet!aber!ccs   JNT: ccs@uk.ac.aber
+          Deddf Iaith Newydd i Gymru | New Language Act for Wales
+
+From: ccs@aber.ac.uk (Christopher Samuel)
+Date:  2-OCT-1992  11:36:37
+Description: Creating a new "alt" group -- guidelines
+
+Archive-name: alt-config-guide
+Version: 1.2
+Last-modified: Wed Sep  2 16:31:55 GMT 1992
+ 
+ 
+ 
+		Guidelines for the creation of an "alt" group.
+ 
+There are no rules or guidelines for creation of "alt" groups, However
+there does appear to be an established procedure which follows.  First a
+quick bit of common-sense on choosing the name:
+ 
+When choosing a name for a group please note the only commandment: Thou
+shalt not choose a group name which may cause network harm or harm to a
+local machine. 
+ 
+          Examples:
+ 
+          alt.fan.enya.puke.puke.pukeSender:
+ 
+          [preceding line to Sender had <CR> deleted; also the
+           trailing : can cause problems in some news systems]
+ 
+          alt.verylonggroupnamethathasadirectorylongerthanmost\
+          machinessupportsotherehaha.very.funny
+ 
+          alt.[insert300charactershere].very.long.group.name.\
+          that.is.too.big.for.newsrc
+ 
+          alt.*.this.name.has.bad.characters.in.it
+ 
+          alt..double.dot.group.name
+ 
+ 
+		Now the Guidelines:
+		-------------------
+ 
+       1) Propose a new alt group in alt.config.  The proposal
+          should include a charter or purpose for the new group, and
+          some demonstration of the need for the group.  It is best to
+          make it clear in your subject line that you are proposing a
+          new group. Be prepared to explain why an existing group cannot
+          be used for this purpose, and why the group should be in "alt"
+          rather than in one of the mainstream hierarchies (like
+          "rec", "sci", etc.).  Avoiding the complexity of the
+          mainstream group creation procedure is not a very good
+          reason, groups should not be created in "alt" just because
+          it's easier.  Don't forget that mainstream groups can also
+          be created by the "trial" mechanism.  Many sites do not get
+          any alt groups, so if you are proposing a serious group, it
+          is worth the effort to try to get it into a mainstream
+          hierarchy.
+ 
+       2) See what the alt.net.opinion of the new group is.  Wait a
+          few days for replies to trickle in from the far corners of
+          the net.  If the consensus (however you determine that) is
+          that the group should be created, then proceed to step 3.
+ 
+          (these first two steps are often ignored, which usually
+          leads to unpleasantness in step 4 below)
+ 
+       3) Post a "newgroup" control message.  If you don't know
+          how to do this, check with your news administrator.  If you
+          ARE your news administrator, and you can't figure it out
+          from the documentation you have (or don't have any
+          documentation) send me mail and I will help you.  NOTE that
+          many sites do NOT automatically honor "newgroup" and
+          "rmgroup" control messages, the news software at these sites
+          will send mail to the news administrator, who will evaluate
+          your request and decide whether or not to create the group.
+          It may take a couple of days for the control message to
+          propagate and be acted upon, so don't expect instant
+          availability of the new group, particularly if you post the
+          control message on a Friday night.
+ 
+          NB:	It is good manners to put a description of the new
+          	newsgroup into the newgroup message, along with a
+          	one-line description suitable for inclusion into the
+          	newsgroups file.
+ 
+       4) Let the individual site news administrators decide
+          whether to honor your "newgroup" message.  Most admins
+          prefer that the message come from a verifiable account,
+          messages which are obviously forged, or have not been
+          discussed in alt.config and contain no explanation will
+          probably not be honored by many sites.  Persons opposed to
+          the group, or admins who feel that the newgroup message was
+          a forgery may send out "rmgroup" messages to try to sabotage
+          the group.  It may take several iterations of this process
+          to firmly establish the new group.  It has been humorously
+          suggested that only alt groups which get 100 more "newgroup"
+          than "rmgroup" messages should be established.  However,
+          these "rmgroup wars" are annoying to news administrators,
+          and reduce the overall acceptance (and distribution) of the
+          "alt" hierarchy.  This is the reason that steps 1 and 2
+          above are important.
+ 
+ 
+This may sound like a lot of rigamarole, and it is.  The purpose is to
+discourage creation of alt groups that might be better off as mainstream
+groups, or that might be better of left uncreated.
+ 
+Don't take this all too seriously, though.  The "alt" net is the last
+remaining refuge away from the control freaks, namespace purists and
+net.cops (like myself) that maintain and enforce the mainstream
+newsgroup guidelines.
+ 
+There is still some room for spontaneity out here on the "alt" frontier. 
+Successful groups have been created without following these suggestions. 
+Almost any non-forged, serious newgroup message will at least be
+considered by most news admins.  Some groups have been created just on a
+whim.  The concept behind the group better be good (or a least
+entertaining), though!
+ 
+[ If you want more information on mainstream group creation see the post
+  "How to Create a New Newsgroup" posted to news.answers, news.admin and
+  news.groups. ]
+ 
+-- 
+ Christopher Samuel, c/o Computer Unit, UCW Aberystwyth, Aberystwyth, WALES
+  RFC: ccs@aber.ac.uk   UUCP: *!mcsun!uknet!aber!ccs   JNT: ccs@uk.ac.aber
+          Deddf Iaith Newydd i Gymru | New Language Act for Wales
diff --git a/decus/vmslt98a/bulletin/news.com b/decus/vmslt98a/bulletin/news.com
new file mode 100755
index 0000000000000000000000000000000000000000..2889055e732fbe1ef7ce37abdd452eb03b381e70
--- /dev/null
+++ b/decus/vmslt98a/bulletin/news.com
@@ -0,0 +1,679 @@
+$set nover
+$copy/log sys$input NEWS.ALT
+$deck
+
+From: ccs@aber.ac.uk (Christopher Samuel)
+Date:  2-OCT-1992  11:36:37
+Description: Creating a new "alt" group -- guidelines
+
+Archive-name: alt-config-guide
+Version: 1.2
+Last-modified: Wed Sep  2 16:31:55 GMT 1992
+ 
+ 
+ 
+		Guidelines for the creation of an "alt" group.
+ 
+There are no rules or guidelines for creation of "alt" groups, However
+there does appear to be an established procedure which follows.  First a
+quick bit of common-sense on choosing the name:
+ 
+When choosing a name for a group please note the only commandment: Thou
+shalt not choose a group name which may cause network harm or harm to a
+local machine. 
+ 
+          Examples:
+ 
+          alt.fan.enya.puke.puke.pukeSender:
+ 
+          [preceding line to Sender had <CR> deleted; also the
+           trailing : can cause problems in some news systems]
+ 
+          alt.verylonggroupnamethathasadirectorylongerthanmost\
+          machinessupportsotherehaha.very.funny
+ 
+          alt.[insert300charactershere].very.long.group.name.\
+          that.is.too.big.for.newsrc
+ 
+          alt.*.this.name.has.bad.characters.in.it
+ 
+          alt..double.dot.group.name
+ 
+ 
+		Now the Guidelines:
+		-------------------
+ 
+       1) Propose a new alt group in alt.config.  The proposal
+          should include a charter or purpose for the new group, and
+          some demonstration of the need for the group.  It is best to
+          make it clear in your subject line that you are proposing a
+          new group. Be prepared to explain why an existing group cannot
+          be used for this purpose, and why the group should be in "alt"
+          rather than in one of the mainstream hierarchies (like
+          "rec", "sci", etc.).  Avoiding the complexity of the
+          mainstream group creation procedure is not a very good
+          reason, groups should not be created in "alt" just because
+          it's easier.  Don't forget that mainstream groups can also
+          be created by the "trial" mechanism.  Many sites do not get
+          any alt groups, so if you are proposing a serious group, it
+          is worth the effort to try to get it into a mainstream
+          hierarchy.
+ 
+       2) See what the alt.net.opinion of the new group is.  Wait a
+          few days for replies to trickle in from the far corners of
+          the net.  If the consensus (however you determine that) is
+          that the group should be created, then proceed to step 3.
+ 
+          (these first two steps are often ignored, which usually
+          leads to unpleasantness in step 4 below)
+ 
+       3) Post a "newgroup" control message.  If you don't know
+          how to do this, check with your news administrator.  If you
+          ARE your news administrator, and you can't figure it out
+          from the documentation you have (or don't have any
+          documentation) send me mail and I will help you.  NOTE that
+          many sites do NOT automatically honor "newgroup" and
+          "rmgroup" control messages, the news software at these sites
+          will send mail to the news administrator, who will evaluate
+          your request and decide whether or not to create the group.
+          It may take a couple of days for the control message to
+          propagate and be acted upon, so don't expect instant
+          availability of the new group, particularly if you post the
+          control message on a Friday night.
+ 
+          NB:	It is good manners to put a description of the new
+          	newsgroup into the newgroup message, along with a
+          	one-line description suitable for inclusion into the
+          	newsgroups file.
+ 
+       4) Let the individual site news administrators decide
+          whether to honor your "newgroup" message.  Most admins
+          prefer that the message come from a verifiable account,
+          messages which are obviously forged, or have not been
+          discussed in alt.config and contain no explanation will
+          probably not be honored by many sites.  Persons opposed to
+          the group, or admins who feel that the newgroup message was
+          a forgery may send out "rmgroup" messages to try to sabotage
+          the group.  It may take several iterations of this process
+          to firmly establish the new group.  It has been humorously
+          suggested that only alt groups which get 100 more "newgroup"
+          than "rmgroup" messages should be established.  However,
+          these "rmgroup wars" are annoying to news administrators,
+          and reduce the overall acceptance (and distribution) of the
+          "alt" hierarchy.  This is the reason that steps 1 and 2
+          above are important.
+ 
+ 
+This may sound like a lot of rigamarole, and it is.  The purpose is to
+discourage creation of alt groups that might be better off as mainstream
+groups, or that might be better of left uncreated.
+ 
+Don't take this all too seriously, though.  The "alt" net is the last
+remaining refuge away from the control freaks, namespace purists and
+net.cops (like myself) that maintain and enforce the mainstream
+newsgroup guidelines.
+ 
+There is still some room for spontaneity out here on the "alt" frontier. 
+Successful groups have been created without following these suggestions. 
+Almost any non-forged, serious newgroup message will at least be
+considered by most news admins.  Some groups have been created just on a
+whim.  The concept behind the group better be good (or a least
+entertaining), though!
+ 
+[ If you want more information on mainstream group creation see the post
+  "How to Create a New Newsgroup" posted to news.answers, news.admin and
+  news.groups. ]
+ 
+-- 
+ Christopher Samuel, c/o Computer Unit, UCW Aberystwyth, Aberystwyth, WALES
+  RFC: ccs@aber.ac.uk   UUCP: *!mcsun!uknet!aber!ccs   JNT: ccs@uk.ac.aber
+          Deddf Iaith Newydd i Gymru | New Language Act for Wales
+
+From: ccs@aber.ac.uk (Christopher Samuel)
+Date:  2-OCT-1992  11:36:37
+Description: Creating a new "alt" group -- guidelines
+
+Archive-name: alt-config-guide
+Version: 1.2
+Last-modified: Wed Sep  2 16:31:55 GMT 1992
+ 
+ 
+ 
+		Guidelines for the creation of an "alt" group.
+ 
+There are no rules or guidelines for creation of "alt" groups, However
+there does appear to be an established procedure which follows.  First a
+quick bit of common-sense on choosing the name:
+ 
+When choosing a name for a group please note the only commandment: Thou
+shalt not choose a group name which may cause network harm or harm to a
+local machine. 
+ 
+          Examples:
+ 
+          alt.fan.enya.puke.puke.pukeSender:
+ 
+          [preceding line to Sender had <CR> deleted; also the
+           trailing : can cause problems in some news systems]
+ 
+          alt.verylonggroupnamethathasadirectorylongerthanmost\
+          machinessupportsotherehaha.very.funny
+ 
+          alt.[insert300charactershere].very.long.group.name.\
+          that.is.too.big.for.newsrc
+ 
+          alt.*.this.name.has.bad.characters.in.it
+ 
+          alt..double.dot.group.name
+ 
+ 
+		Now the Guidelines:
+		-------------------
+ 
+       1) Propose a new alt group in alt.config.  The proposal
+          should include a charter or purpose for the new group, and
+          some demonstration of the need for the group.  It is best to
+          make it clear in your subject line that you are proposing a
+          new group. Be prepared to explain why an existing group cannot
+          be used for this purpose, and why the group should be in "alt"
+          rather than in one of the mainstream hierarchies (like
+          "rec", "sci", etc.).  Avoiding the complexity of the
+          mainstream group creation procedure is not a very good
+          reason, groups should not be created in "alt" just because
+          it's easier.  Don't forget that mainstream groups can also
+          be created by the "trial" mechanism.  Many sites do not get
+          any alt groups, so if you are proposing a serious group, it
+          is worth the effort to try to get it into a mainstream
+          hierarchy.
+ 
+       2) See what the alt.net.opinion of the new group is.  Wait a
+          few days for replies to trickle in from the far corners of
+          the net.  If the consensus (however you determine that) is
+          that the group should be created, then proceed to step 3.
+ 
+          (these first two steps are often ignored, which usually
+          leads to unpleasantness in step 4 below)
+ 
+       3) Post a "newgroup" control message.  If you don't know
+          how to do this, check with your news administrator.  If you
+          ARE your news administrator, and you can't figure it out
+          from the documentation you have (or don't have any
+          documentation) send me mail and I will help you.  NOTE that
+          many sites do NOT automatically honor "newgroup" and
+          "rmgroup" control messages, the news software at these sites
+          will send mail to the news administrator, who will evaluate
+          your request and decide whether or not to create the group.
+          It may take a couple of days for the control message to
+          propagate and be acted upon, so don't expect instant
+          availability of the new group, particularly if you post the
+          control message on a Friday night.
+ 
+          NB:	It is good manners to put a description of the new
+          	newsgroup into the newgroup message, along with a
+          	one-line description suitable for inclusion into the
+          	newsgroups file.
+ 
+       4) Let the individual site news administrators decide
+          whether to honor your "newgroup" message.  Most admins
+          prefer that the message come from a verifiable account,
+          messages which are obviously forged, or have not been
+          discussed in alt.config and contain no explanation will
+          probably not be honored by many sites.  Persons opposed to
+          the group, or admins who feel that the newgroup message was
+          a forgery may send out "rmgroup" messages to try to sabotage
+          the group.  It may take several iterations of this process
+          to firmly establish the new group.  It has been humorously
+          suggested that only alt groups which get 100 more "newgroup"
+          than "rmgroup" messages should be established.  However,
+          these "rmgroup wars" are annoying to news administrators,
+          and reduce the overall acceptance (and distribution) of the
+          "alt" hierarchy.  This is the reason that steps 1 and 2
+          above are important.
+ 
+ 
+This may sound like a lot of rigamarole, and it is.  The purpose is to
+discourage creation of alt groups that might be better off as mainstream
+groups, or that might be better of left uncreated.
+ 
+Don't take this all too seriously, though.  The "alt" net is the last
+remaining refuge away from the control freaks, namespace purists and
+net.cops (like myself) that maintain and enforce the mainstream
+newsgroup guidelines.
+ 
+There is still some room for spontaneity out here on the "alt" frontier. 
+Successful groups have been created without following these suggestions. 
+Almost any non-forged, serious newgroup message will at least be
+considered by most news admins.  Some groups have been created just on a
+whim.  The concept behind the group better be good (or a least
+entertaining), though!
+ 
+[ If you want more information on mainstream group creation see the post
+  "How to Create a New Newsgroup" posted to news.answers, news.admin and
+  news.groups. ]
+ 
+-- 
+ Christopher Samuel, c/o Computer Unit, UCW Aberystwyth, Aberystwyth, WALES
+  RFC: ccs@aber.ac.uk   UUCP: *!mcsun!uknet!aber!ccs   JNT: ccs@uk.ac.aber
+          Deddf Iaith Newydd i Gymru | New Language Act for Wales
+$eod 
+$copy/log sys$input NEWS.CREATE
+$deck
+From: tale@uunet.uu.net (David C Lawrence)
+Date: 19-OCT-1992  00:15:29
+Description: How to Create a New Usenet Newsgroup
+
+Archive-name: creating-newsgroups/part1
+Original-author: woods@ncar.ucar.edu (Greg Woods)
+Last-change: 23 Sep 1992 by spaf@cs.purdue.edu (Gene Spafford)
+ 
+				 GUIDELINES FOR USENET GROUP CREATION
+ 
+REQUIREMENTS FOR GROUP CREATION:
+ 
+   These are guidelines that have been generally agreed upon across
+USENET as appropriate for following in the creating of new newsgroups in
+the "standard" USENET newsgroup hierarchy. They are NOT intended as 
+guidelines for setting USENET policy other than group creations, and they
+are not intended to apply to "alternate" or local news hierarchies. The 
+part of the namespace affected is comp, news, sci, misc, soc, talk, rec,
+which are the most widely-distributed areas of the USENET hierarchy.
+   Any group creation request which follows these guidelines to a
+successful result should be honored, and any request which fails to
+follow these procedures or to obtain a successful result from doing so
+should be dropped, except under extraordinary circumstances.  The
+reason these are called guidelines and not absolute rules is that it is
+not possible to predict in advance what "extraordinary circumstances"
+are or how they might arise.
+   It should be pointed out here that, as always, the decision whether or not
+to create a newsgroup on a given machine rests with the administrator of that
+machine. These guidelines are intended merely as an aid in making those
+decisions.
+ 
+ 
+The Discussion
+ 
+1) A request for discussion on creation of a new newsgroup should be posted to
+   news.announce.newgroups, and also to any other groups or mailing lists at
+   all related to the proposed topic if desired.  The group is moderated, and
+   the Followup-to: header will be set so that the actual discussion takes
+   place only in news.groups.  Users on sites which have difficulty posting to
+   moderated groups may mail submissions intended for news.announce.newgroups
+   to announce-newgroups@uunet.uu.net.
+ 
+   The article should be cross-posted among the newsgroups, including
+   news.announce.newgroups, rather than posted as separate articles.  Note that
+   standard behaviour for posting software is to not present the articles in
+   any groups when cross-posted to a moderated group; the moderator will handle
+   that for you.
+ 
+2) The name and charter of the proposed group and whether it will be moderated
+   or unmoderated (and if the former, who the moderator(s) will be) should be
+   determined during the discussion period. If there is no general agreement on
+   these points among the proponents of a new group at the end of 30 days of
+   discussion, the discussion should be taken offline (into mail instead of
+   news.groups) and the proponents should iron out the details among
+   themselves.  Once that is done, a new, more specific proposal may be made,
+   going back to step 1) above.  
+ 
+3) Group advocates seeking help in choosing a name to suit the proposed
+   charter, or looking for any other guidance in the creation procedure, can
+   send a message to group-advice@uunet.uu.net; a few seasoned news administrators
+   are available through this address.
+ 
+The Vote
+ 
+1) AFTER the discussion period, if it has been determined that a new group is
+   really desired, a name and charter are agreed upon, and it has been
+   determined whether the group will be moderated and if so who will
+   moderate it, a call for votes may be posted to news.announce.newgroups and
+   any other groups or mailing lists that the original request for discussion
+   might have been posted to. There should be minimal delay between the
+   end of the discussion period and the issuing of a call for votes.
+   The call for votes should include clear instructions for how to cast
+   a vote. It must be as clearly explained and as easy to do to cast a
+   vote for creation as against it, and vice versa.  It is explicitly
+   permitted to set up two separate addresses to mail yes and no votes
+   to provided that they are on the same machine, to set up an address
+   different than that the article was posted from to mail votes to, or
+   to just accept replies to the call for votes article, as long as it
+   is clearly and explicitly stated in the call for votes article how
+   to cast a vote.  If two addresses are used for a vote, the reply
+   address must process and accept both yes and no votes OR reject
+   them both.
+ 
+2) The voting period should last for at least 21 days and no more than 31
+   days, no matter what the preliminary results of the vote are. The exact
+   date that the voting period will end should be stated in the call for
+   votes. Only votes that arrive on the vote-taker's machine prior to this
+   date will be counted.
+ 
+3) A couple of repeats of the call for votes may be posted during the vote, 
+   provided that they contain similar clear, unbiased instructions for
+   casting a vote as the original, and provided that it is really a repeat
+   of the call for votes on the SAME proposal (see #5 below). Partial vote
+   results should NOT be included; only a statement of the specific new
+   group proposal, that a vote is in progress on it, and how to cast a vote.
+   It is permitted to post a "mass acknowledgement" in which all the names
+   of those from whom votes have been received are posted, as long as no
+   indication is made of which way anybody voted until the voting period
+   is officially over.
+ 
+4) ONLY votes MAILED to the vote-taker will count. Votes posted to the net
+   for any reason (including inability to get mail to the vote-taker) and 
+   proxy votes (such as having a mailing list maintainer claim a vote for 
+   each member of the list) will not be counted.
+ 
+5) Votes may not be transferred to other, similar proposals. A vote shall
+   count only for the EXACT proposal that it is a response to. In particular,
+   a vote for or against a newsgroup under one name shall NOT be counted as
+   a vote for or against a newsgroup with a different name or charter,
+   a different moderated/unmoderated status or (if moderated) a different
+   moderator or set of moderators.
+ 
+6) Votes MUST be explicit; they should be of the form "I vote for the
+   group foo.bar as proposed" or "I vote against the group foo.bar
+   as proposed". The wording doesn't have to be exact, it just needs to
+   be unambiguous. In particular, statements of the form "I would vote
+   for this group if..." should be considered comments only and not
+   counted as votes.
+ 
+7) A vote should be run only for a single group proposal.  Attempts to create
+   multiple groups should be handled by running multiple parallel votes rather
+   than one vote to create all of the groups.
+ 
+The Result
+ 
+1) At the completion of the voting period, the vote taker must post the
+   vote tally and the E-mail addresses and (if available) names of the voters
+   received to news.announce.newgroups and any other groups or mailing lists
+   to which the original call for votes was posted. The tally should include
+   a statement of which way each voter voted so that the results can be
+   verified.
+ 
+2) AFTER the vote result is posted, there will be a 5 day waiting period,
+   beginning when the voting results actually appear in 
+   news.announce.newgroups, during which the net will have a chance to
+   correct any errors in the voter list or the voting procedure.
+ 
+3) AFTER the waiting period, and if there were no serious objections that might
+   invalidate the vote, and if 100 more valid YES/create votes are received
+   than NO/don't create AND at least 2/3 of the total number of valid votes
+   received are in favor of creation, a newgroup control message may be sent 
+   out.  If the 100 vote margin or 2/3 percentage is not met, the group should 
+   not be created.
+ 
+4) The newgroup message will be sent by the news.announce.newgroups moderator
+   at the end of the waiting period of a successful vote.  If the new group is
+   moderated, the vote-taker should send a message during the waiting period to
+   Gene Spafford <spaf@cs.purdue.edu> and David C. Lawrence <tale@uunet.uu.net> with
+   both the moderator's contact address and the group's submission address.
+ 
+5) A proposal which has failed under point (3) above should not again be
+   brought up for discussion until at least six months have passed from the
+   close of the vote.  This limitation does not apply to proposals which never
+   went to vote.
+ 
+$eod 
+$copy/log sys$input NEWS.MODERATORS
+$deck
+comp.ai.nlang-know-rep		nl-kr@cs.rpi.edu
+comp.ai.vision			vision-list@ads.com
+comp.archives			comp-archives@msen.com
+comp.binaries.acorn		cba@acorn.co.nz
+comp.binaries.amiga		amiga@uunet.uu.net
+comp.binaries.atari.st		atari-binaries@hyperion.com
+comp.binaries.ibm.pc		cbip@cs.ulowell.edu
+comp.binaries.mac		macintosh%felix.uucp@uunet.uu.net
+comp.binaries.os2		os2bin@csd4.csd.uwm.edu
+comp.bugs.4bsd.ucb-fixes	ucb-fixes@okeeffe.berkeley.edu
+comp.compilers			compilers@iecc.cambridge.ma.us
+comp.dcom.telecom		telecom@eecs.nwu.edu
+comp.doc			comp-doc@ucsd.edu
+comp.doc.techreports		compdoc-techreports@ftp.cse.ucsc.edu
+comp.graphics.research		graphics@scri1.scri.fsu.edu
+comp.internet.library		library@axon.cwru.edu
+comp.lang.sigplan		sigplan@bellcore.com
+comp.laser-printers		laser-lovers@brillig.umd.edu
+comp.mail.maps			uucpmap@rutgers.edu
+comp.newprod			newprod@chg.mcd.mot.com
+comp.org.eff.news		effnews@eff.org
+comp.org.fidonet		pozar@hop.toad.com
+comp.os.ms-windows.announce	infidel+win-announce@pitt.edu
+comp.os.research		osr@ftp.cse.ucsc.edu
+comp.parallel			hypercube@hubcap.clemson.edu
+comp.patents			patents@cs.su.oz.au
+comp.protocols.kermit		info-kermit@watsun.cc.columbia.edu
+comp.research.japan		japan@cs.arizona.edu
+comp.risks			risks@csl.sri.com
+comp.simulation			simulation@uflorida.cis.ufl.edu
+comp.society			socicom@auvm.american.edu
+comp.society.cu-digest		tk0jut2@mvs.cso.niu.edu
+comp.society.folklore		folklore@snark.thyrsus.com
+comp.society.privacy		comp-privacy@pica.army.mil
+comp.sources.3b1		comp-sources-3b1@galaxia.network23.com
+comp.sources.acorn		cba@acorn.co.nz
+comp.sources.amiga		amiga@uunet.uu.net
+comp.sources.apple2		jac@paul.rutgers.edu
+comp.sources.atari.st		atari-sources@hyperion.com
+comp.sources.games		games@saab.cna.tek.com
+comp.sources.hp48		hp48@seq.uncwil.edu
+comp.sources.mac		macintosh%felix.uucp@uunet.uu.net
+comp.sources.misc		sources-misc@uunet.uu.net
+comp.sources.reviewed		csr@calvin.dgbt.doc.ca
+comp.sources.sun		sun-sources@topaz.rutgers.edu
+comp.sources.unix		unix-sources-moderator@pa.dec.com
+comp.sources.x			x-sources@msi.com
+comp.std.announce		klensin@infoods.mit.edu
+comp.std.mumps			std-mumps@pfcs.com
+comp.std.unix			std-unix@uunet.uu.net
+comp.sys.acorn.announce		announce@acorn.co.uk
+comp.sys.amiga.announce		announce@cs.ucdavis.edu
+comp.sys.amiga.reviews		amiga-reviews-submissions@math.uh.edu
+comp.sys.concurrent		concurrent@bdcsys.suvl.ca.us
+comp.sys.ibm.pc.digest		info-ibmpc@simtel20.army.mil
+comp.sys.m68k.pc		info-68k@ucbvax.berkeley.edu
+comp.sys.mac.announce		csma@rascal.ics.utexas.edu
+comp.sys.mac.digest		info-mac@sumex-aim.stanford.edu
+comp.sys.next.announce		csn-announce@liveware.com
+comp.sys.sun.announce		sun-announce@sunworld.com
+comp.theory.info-retrieval	ir-l%uccvma.bitnet@berkeley.edu
+comp.virus			krvw@cert.org
+comp.windows.x.announce		xannounce@expo.lcs.mit.edu
+misc.activism.progressive	map@pencil.cs.missouri.edu
+misc.handicap			handicap@bunker.shel.isc-br.com
+misc.news.southasia		surekha@nyx.cs.du.edu
+news.admin.technical		natech@zorch.sf-bay.org
+news.announce.conferences	nac@tekbspa.tss.com
+news.announce.important		announce@stargate.com
+news.announce.newgroups		announce-newgroups@rpi.edu
+news.announce.newusers		spaf@cs.purdue.edu
+news.answers			news-answers@mit.edu
+news.lists			news-lists-request@cs.purdue.edu
+news.lists.ps-maps		reid@decwrl.dec.com
+rec.arts.cinema			cinema@zerkalo.harvard.edu
+rec.arts.comics.info		info_comic@dartmouth.edu
+rec.arts.erotica		erotica@telly.on.ca
+rec.arts.movies.reviews		movies@mtgzy.att.com
+rec.arts.sf.announce		sf-announce@zorch.sf-bay.org
+rec.arts.sf.reviews		sf-reviews@presto.ig.com
+rec.arts.startrek.info		trek-info@dweeb.fx.com
+rec.audio.high-end		info-high-audio@csd4.csd.uwm.edu
+rec.food.recipes		recipes@mthvax.cs.miami.edu
+rec.games.cyber			cyberrpg@veritas.com
+rec.games.frp.announce		rg-frp-announce@magnus.acs.ohio-state.edu
+rec.games.frp.archives		frp-archives@rpi.edu
+rec.games.mud.announce		rgm-announce@glia.biostr.washington.edu
+rec.guns			magnum@flubber.cs.umd.edu
+rec.humor.funny			funny@clarinet.com
+rec.humor.oracle		oracle-mod@cs.indiana.edu
+rec.hunting			hunting@osnome.che.wisc.edu
+rec.mag.fsfnet			white@duvm.bitnet
+rec.music.gaffa			love-hounds@uunet.uu.net
+rec.music.info			rec-music-info@ph.tn.tudelft.nl
+rec.music.reviews		music_reviews@sco.com
+rec.radio.broadcasting		rrb@airwaves.chi.il.us
+rec.sport.cricket.scores	cricket@power.eee.ndsu.nodak.edu
+sci.astro.hubble		sah@wfpc3.la.asu.edu
+sci.math.research		sci-math-research@uiuc.edu
+sci.med.aids			aids@cs.ucla.edu
+sci.military			military@att.att.com
+sci.nanotech			nanotech@aramis.rutgers.edu
+sci.psychology.digest		psyc@phoenix.princeton.edu
+sci.space.news			sci-space-news@news.arc.nasa.gov
+sci.virtual-worlds		virtual-worlds@milton.u.washington.edu
+soc.feminism			feminism@ncar.ucar.edu
+soc.politics			poli-sci@rutgers.edu
+soc.politics.arms-d		arms-d@xx.lcs.mit.edu
+soc.religion.bahai		srb@oneworld.wa.com
+soc.religion.christian		christian@aramis.rutgers.edu
+soc.religion.eastern		sre@cse.ogi.edu
+soc.religion.islam		religion-islam@ncar.ucar.edu
+alt.atheism.moderated		atheism@mantis.co.uk
+alt.binaries.pictures.fine-art.d	artcomp@uxa.ecn.bgu.edu
+alt.binaries.pictures.fine-art.digitized	artcomp@uxa.ecn.bgu.edu
+alt.binaries.pictures.fine-art.graphics	artcomp@uxa.ecn.bgu.edu
+alt.comp.acad-freedom.news	caf-news@eff.org
+alt.dev.null			/dev/null
+alt.gourmand			recipes@decwrl.dec.com
+alt.hackers			/dev/null
+alt.hindu			editor@rbhatnagar.csm.uc.edu
+alt.politics.democrats		news-submit@dc.clinton-gore.org
+alt.politics.democrats.clinton	news-submit@dc.clinton-gore.org
+alt.politics.democrats.governors	news-submit@dc.clinton-gore.org
+alt.politics.democrats.house	news-submit@dc.clinton-gore.org
+alt.politics.democrats.senate	news-submit@dc.clinton-gore.org
+alt.security.index		kyle@uunet.uu.net
+alt.society.ati			gzero@tronsbox.xei.com
+alt.society.cu-digest		tk0jut2@mvs.cso.niu.edu
+alt.sources.index		kyle@uunet.uu.net
+austin.eff			eff-austin-moderator@tic.com
+ba.announce			ba-announce@zorch.sf-bay.org
+bionet.announce			biosci-announce-moderator@genbank.bio.net
+bionet.biology.computational	comp-bio-moderator@genbank.bio.net
+bionet.molbio.ddbj.updates	ddbj-updates@genbank.bio.net
+bionet.molbio.embldatabank.updates	embl-updates@genbank.bio.net
+bionet.molbio.genbank.updates	lear@genbank.bio.net
+bionet.software.sources		software-sources@genbank.bio.net
+bit.listserv.big-lan		big-req@suvm.acs.syr.edu
+bit.listserv.edtech		21765EDT%MSU@CUNYVM.CUNY.EDU
+bit.listserv.gaynet		gaynet@athena.mit.edu
+bit.listserv.hellas		sda106@psuvm.psu.edu
+bit.listserv.l-hcap		wtm@bunker.shel.isc-br.com
+bit.listserv.libres		librk329@KentVMS.Kent.edu
+bit.listserv.new-list		NU021172@VM1.NoDak.EDU
+bit.listserv.pacs-l		LIBPACS%UHUPVM1@CUNYVM.CUNY.EDU
+bit.listserv.valert-l		krvw@cert.org
+biz.dec.decnews			decnews@mr4dec.enet.dec.com
+biz.sco.announce		scoannmod@xenitec.on.ca
+biz.sco.binaries		sl@wimsey.bc.ca
+biz.sco.sources			kd1hz@anomaly.sbs.risc.net
+biz.zeos.announce		kgermann@zeos.com
+can.canet.d			canet-d@canet.ca
+can.uucp.maps			pathadmin@cs.toronto.edu
+comp.protocols.iso.x400.gateway	ifip-gtwy-usenet@ics.uci.edu
+comp.security.announce		cert@cert.org
+ddn.mgt-bulletin		nic@nic.ddn.mil
+ddn.newsletter			nic@nic.ddn.mil
+de.admin.lists			de-admin-lists@hactar.hanse.de
+de.admin.submaps		maps@flatlin.ka.sub.org
+de.comp.sources.amiga		agnus@amylnd.stgt.sub.org
+de.comp.sources.misc		sources@watzman.quest.sub.org
+de.comp.sources.os9		fkk@stasys.sta.sub.org
+de.comp.sources.st		sources-st@watzman.quest.sub.org
+de.comp.sources.unix		de-comp-sources-unix@germany.sun.com
+de.mag.chalisti			ccc@sol.ccc.de
+de.newusers			newusers@jattmp.nbg.sub.org
+de.org.dfn			org-dfn@dfn.de
+de.org.eunet			news@germany.eu.net
+de.org.sub			vorstand@smurf.sub.org
+de.sci.ki			hein@damon.irf.uni-dortmund.de
+de.sci.ki.mod.ki		hein@damon.irf.uni-dortmund.de
+fj.announce			fj-announce@junet.ad.jp
+fj.binaries			fj-binaries@junet.ad.jp
+fj.binaries.x68000		fj-binaries-x68000@junet.ad.jp
+fj.guide.admin			fj-guide-admin@junet.ad.jp
+fj.guide.general		fj-guide-general@junet.ad.jp
+fj.guide.newusers		fj-guide-newusers@junet.ad.jp
+fj.map				fj-map@junet.ad.jp
+gnu.announce			info-gnu@prep.ai.mit.edu
+gnu.bash.bug			bug-bash@prep.ai.mit.edu
+gnu.emacs.announce		info-gnu-emacs@prep.ai.mit.edu
+gnu.emacs.bug			bug-gnu-emacs@prep.ai.mit.edu
+gnu.g++.announce		info-g++@prep.ai.mit.edu
+gnu.g++.bug			bug-g++@prep.ai.mit.edu
+gnu.g++.lib.bug			bug-lib-g++@prep.ai.mit.edu
+gnu.gcc.announce		info-gcc@prep.ai.mit.edu
+gnu.gcc.bug			bug-gcc@prep.ai.mit.edu
+gnu.gdb.bug			bug-gdb@prep.ai.mit.edu
+gnu.ghostscript.bug		bug-ghostscript@prep.ai.mit.edu
+gnu.groff.bug			bug-groff@prep.ai.mit.edu
+gnu.smalltalk.bug		bug-gnu-smalltalk@prep.ai.mit.edu
+gnu.utils.bug			bug-gnu-utils@prep.ai.mit.edu
+houston.weather			weather-monitor@tmc.edu
+ieee.tcos			tcos@cse.ucsc.edu
+info.academic.freedom		caf-talk@eff.org
+info.admin			usenet@ux1.cso.uiuc.edu
+info.bind			bind@arpa.berkeley.edu
+info.brl.cad			cad@brl.mil
+info.bytecounters		bytecounters@venera.isi.edu
+info.cmu.tek.tcp		cmu-tek-tcp@cs.cmu.edu
+info.convex			info-convex@pemrac.space.swri.edu
+info.firearms			firearms@cs.cmu.edu
+info.firearms.politics		firearms-politics@cs.cmu.edu
+info.gated			gated-people@devvax.tn.cornell.edu
+info.ietf			ietf@venera.isi.edu
+info.ietf.hosts			ietf-hosts@nnsc.nsf.net
+info.ietf.isoc			isoc-interest@relay.sgi.com
+info.ietf.njm			njm@merit.edu
+info.ietf.smtp			ietf-smtp@dimacs.rutgers.edu
+info.isode			isode@nic.ddn.mil
+info.jethro.tull		jtull@remus.rutgers.edu
+info.labmgr			labmgr@ukcc.uky.edu
+info.mach			info-mach@cs.cmu.edu
+info.mh.workers			mh-workers@ics.uci.edu
+info.nets			info-nets@think.com
+info.nsf.grants			grants@note.nsf.gov
+info.nsfnet.cert		nsfnet-cert@merit.edu
+info.nysersnmp			nysersnmp@nisc.nyser.net
+info.osf			roma@uiuc.edu
+info.pem.dev			pem-dev@tis.com
+info.ph				info-ph@uxc.cso.uiuc.edu
+info.rfc			rfc-request@nic.ddn.mil
+info.snmp			snmp@nisc.nyser.net
+info.sun.managers		sun-managers@rice.edu
+info.sun.nets			sun-nets@umiacs.umd.edu
+info.theorynt			theorynt@vm1.nodak.edu
+info.unix.sw			unix-sw-request@wsmr-simtel20.army.mil
+mi.map				uucpmap@rel.mi.org
+opinions.supreme-court		opinions@uunet.uu.net
+relcom.infomarket.quote		relcom-infomarket-quote@news.ussr.eu.net
+relcom.infomarket.talk		relcom-infomarket-talk@news.ussr.eu.net
+relcom.jusinf			relcom-jusinf@news.ussr.eu.net
+relcom.postmasters		relcom-postmasters@news.ussr.eu.net
+relcom.renews			relcom-renews@news.ussr.eu.net
+resif.oracle			oracle@grasp1.univ-lyon1.fr
+sfnet.atk.flpf.tiedotukset	flpf@nic.funet.fi
+sfnet.csc.tiedotukset		netmgr@csc.fi
+sfnet.funet.tiedotukset		toimitus@funet.fi
+sfnet.fuug.tiedotukset		sfnet-fuug-tiedotukset@fuug.fi
+sfnet.harrastus.astronomia	pvtmakela@cc.helsinki.fi
+sfnet.harrastus.mensa		jau@cs.tut.fi
+sfnet.lists.sunflash		flash@sunvice.East.Sun.COM
+sfnet.opiskelu.ymp.kurssit	hoffren@cc.Helsinki.FI
+sfnet.tiede.tilastotiede.jatkokoulutus	til_tied@cc.helsinki.fi
+sura.announce			sura-announce@darwin.sura.net
+sura.noc.status			sura-noc-status@darwin.sura.net
+sura.security			sura-security@darwin.sura.net
+tamu.religion.christian		shetler@eemips.tamu.edu
+tx-thenet-managers		themgr-moderator@nic.the.net
+tx.maps				texas-uucpmaps@tmc.edu
+uiuc.org.men			uiuc-men-ml@ux1.cso.uiuc.edu
+uunet.alternet			asp@uunet.uu.net,postman@uunet.uu.net
+uunet.announce			postman@uunet.uu.net
+uunet.products			postman@uunet.uu.net
+uunet.status			postman@uunet.uu.net
+uunet.tech			postman@uunet.uu.net
+vmsnet.announce			vmsnet-announce@mccall.com
+vmsnet.announce.newusers	vmsnet-announce-newusers@mccall.com
+vmsnet.sources			vmsnet-sources@mvb.saic.com
+$eod 
diff --git a/decus/vmslt98a/bulletin/news.create b/decus/vmslt98a/bulletin/news.create
new file mode 100755
index 0000000000000000000000000000000000000000..7f28ba6808b5ebf91f2f950822ae37e024c898f2
--- /dev/null
+++ b/decus/vmslt98a/bulletin/news.create
@@ -0,0 +1,155 @@
+From: tale@uunet.uu.net (David C Lawrence)
+Date: 19-OCT-1992  00:15:29
+Description: How to Create a New Usenet Newsgroup
+
+Archive-name: creating-newsgroups/part1
+Original-author: woods@ncar.ucar.edu (Greg Woods)
+Last-change: 23 Sep 1992 by spaf@cs.purdue.edu (Gene Spafford)
+ 
+				 GUIDELINES FOR USENET GROUP CREATION
+ 
+REQUIREMENTS FOR GROUP CREATION:
+ 
+   These are guidelines that have been generally agreed upon across
+USENET as appropriate for following in the creating of new newsgroups in
+the "standard" USENET newsgroup hierarchy. They are NOT intended as 
+guidelines for setting USENET policy other than group creations, and they
+are not intended to apply to "alternate" or local news hierarchies. The 
+part of the namespace affected is comp, news, sci, misc, soc, talk, rec,
+which are the most widely-distributed areas of the USENET hierarchy.
+   Any group creation request which follows these guidelines to a
+successful result should be honored, and any request which fails to
+follow these procedures or to obtain a successful result from doing so
+should be dropped, except under extraordinary circumstances.  The
+reason these are called guidelines and not absolute rules is that it is
+not possible to predict in advance what "extraordinary circumstances"
+are or how they might arise.
+   It should be pointed out here that, as always, the decision whether or not
+to create a newsgroup on a given machine rests with the administrator of that
+machine. These guidelines are intended merely as an aid in making those
+decisions.
+ 
+ 
+The Discussion
+ 
+1) A request for discussion on creation of a new newsgroup should be posted to
+   news.announce.newgroups, and also to any other groups or mailing lists at
+   all related to the proposed topic if desired.  The group is moderated, and
+   the Followup-to: header will be set so that the actual discussion takes
+   place only in news.groups.  Users on sites which have difficulty posting to
+   moderated groups may mail submissions intended for news.announce.newgroups
+   to announce-newgroups@uunet.uu.net.
+ 
+   The article should be cross-posted among the newsgroups, including
+   news.announce.newgroups, rather than posted as separate articles.  Note that
+   standard behaviour for posting software is to not present the articles in
+   any groups when cross-posted to a moderated group; the moderator will handle
+   that for you.
+ 
+2) The name and charter of the proposed group and whether it will be moderated
+   or unmoderated (and if the former, who the moderator(s) will be) should be
+   determined during the discussion period. If there is no general agreement on
+   these points among the proponents of a new group at the end of 30 days of
+   discussion, the discussion should be taken offline (into mail instead of
+   news.groups) and the proponents should iron out the details among
+   themselves.  Once that is done, a new, more specific proposal may be made,
+   going back to step 1) above.  
+ 
+3) Group advocates seeking help in choosing a name to suit the proposed
+   charter, or looking for any other guidance in the creation procedure, can
+   send a message to group-advice@uunet.uu.net; a few seasoned news administrators
+   are available through this address.
+ 
+The Vote
+ 
+1) AFTER the discussion period, if it has been determined that a new group is
+   really desired, a name and charter are agreed upon, and it has been
+   determined whether the group will be moderated and if so who will
+   moderate it, a call for votes may be posted to news.announce.newgroups and
+   any other groups or mailing lists that the original request for discussion
+   might have been posted to. There should be minimal delay between the
+   end of the discussion period and the issuing of a call for votes.
+   The call for votes should include clear instructions for how to cast
+   a vote. It must be as clearly explained and as easy to do to cast a
+   vote for creation as against it, and vice versa.  It is explicitly
+   permitted to set up two separate addresses to mail yes and no votes
+   to provided that they are on the same machine, to set up an address
+   different than that the article was posted from to mail votes to, or
+   to just accept replies to the call for votes article, as long as it
+   is clearly and explicitly stated in the call for votes article how
+   to cast a vote.  If two addresses are used for a vote, the reply
+   address must process and accept both yes and no votes OR reject
+   them both.
+ 
+2) The voting period should last for at least 21 days and no more than 31
+   days, no matter what the preliminary results of the vote are. The exact
+   date that the voting period will end should be stated in the call for
+   votes. Only votes that arrive on the vote-taker's machine prior to this
+   date will be counted.
+ 
+3) A couple of repeats of the call for votes may be posted during the vote, 
+   provided that they contain similar clear, unbiased instructions for
+   casting a vote as the original, and provided that it is really a repeat
+   of the call for votes on the SAME proposal (see #5 below). Partial vote
+   results should NOT be included; only a statement of the specific new
+   group proposal, that a vote is in progress on it, and how to cast a vote.
+   It is permitted to post a "mass acknowledgement" in which all the names
+   of those from whom votes have been received are posted, as long as no
+   indication is made of which way anybody voted until the voting period
+   is officially over.
+ 
+4) ONLY votes MAILED to the vote-taker will count. Votes posted to the net
+   for any reason (including inability to get mail to the vote-taker) and 
+   proxy votes (such as having a mailing list maintainer claim a vote for 
+   each member of the list) will not be counted.
+ 
+5) Votes may not be transferred to other, similar proposals. A vote shall
+   count only for the EXACT proposal that it is a response to. In particular,
+   a vote for or against a newsgroup under one name shall NOT be counted as
+   a vote for or against a newsgroup with a different name or charter,
+   a different moderated/unmoderated status or (if moderated) a different
+   moderator or set of moderators.
+ 
+6) Votes MUST be explicit; they should be of the form "I vote for the
+   group foo.bar as proposed" or "I vote against the group foo.bar
+   as proposed". The wording doesn't have to be exact, it just needs to
+   be unambiguous. In particular, statements of the form "I would vote
+   for this group if..." should be considered comments only and not
+   counted as votes.
+ 
+7) A vote should be run only for a single group proposal.  Attempts to create
+   multiple groups should be handled by running multiple parallel votes rather
+   than one vote to create all of the groups.
+ 
+The Result
+ 
+1) At the completion of the voting period, the vote taker must post the
+   vote tally and the E-mail addresses and (if available) names of the voters
+   received to news.announce.newgroups and any other groups or mailing lists
+   to which the original call for votes was posted. The tally should include
+   a statement of which way each voter voted so that the results can be
+   verified.
+ 
+2) AFTER the vote result is posted, there will be a 5 day waiting period,
+   beginning when the voting results actually appear in 
+   news.announce.newgroups, during which the net will have a chance to
+   correct any errors in the voter list or the voting procedure.
+ 
+3) AFTER the waiting period, and if there were no serious objections that might
+   invalidate the vote, and if 100 more valid YES/create votes are received
+   than NO/don't create AND at least 2/3 of the total number of valid votes
+   received are in favor of creation, a newgroup control message may be sent 
+   out.  If the 100 vote margin or 2/3 percentage is not met, the group should 
+   not be created.
+ 
+4) The newgroup message will be sent by the news.announce.newgroups moderator
+   at the end of the waiting period of a successful vote.  If the new group is
+   moderated, the vote-taker should send a message during the waiting period to
+   Gene Spafford <spaf@cs.purdue.edu> and David C. Lawrence <tale@uunet.uu.net> with
+   both the moderator's contact address and the group's submission address.
+ 
+5) A proposal which has failed under point (3) above should not again be
+   brought up for discussion until at least six months have passed from the
+   close of the vote.  This limitation does not apply to proposals which never
+   went to vote.
+ 
diff --git a/decus/vmslt98a/bulletin/news.moderators b/decus/vmslt98a/bulletin/news.moderators
new file mode 100755
index 0000000000000000000000000000000000000000..7797de207336f92d0320c49f2c3d5e72902fb4c5
--- /dev/null
+++ b/decus/vmslt98a/bulletin/news.moderators
@@ -0,0 +1,260 @@
+comp.ai.nlang-know-rep		nl-kr@cs.rpi.edu
+comp.ai.vision			vision-list@ads.com
+comp.archives			comp-archives@msen.com
+comp.binaries.acorn		cba@acorn.co.nz
+comp.binaries.amiga		amiga@uunet.uu.net
+comp.binaries.atari.st		atari-binaries@hyperion.com
+comp.binaries.ibm.pc		cbip@cs.ulowell.edu
+comp.binaries.mac		macintosh%felix.uucp@uunet.uu.net
+comp.binaries.os2		os2bin@csd4.csd.uwm.edu
+comp.bugs.4bsd.ucb-fixes	ucb-fixes@okeeffe.berkeley.edu
+comp.compilers			compilers@iecc.cambridge.ma.us
+comp.dcom.telecom		telecom@eecs.nwu.edu
+comp.doc			comp-doc@ucsd.edu
+comp.doc.techreports		compdoc-techreports@ftp.cse.ucsc.edu
+comp.graphics.research		graphics@scri1.scri.fsu.edu
+comp.internet.library		library@axon.cwru.edu
+comp.lang.sigplan		sigplan@bellcore.com
+comp.laser-printers		laser-lovers@brillig.umd.edu
+comp.mail.maps			uucpmap@rutgers.edu
+comp.newprod			newprod@chg.mcd.mot.com
+comp.org.eff.news		effnews@eff.org
+comp.org.fidonet		pozar@hop.toad.com
+comp.os.ms-windows.announce	infidel+win-announce@pitt.edu
+comp.os.research		osr@ftp.cse.ucsc.edu
+comp.parallel			hypercube@hubcap.clemson.edu
+comp.patents			patents@cs.su.oz.au
+comp.protocols.kermit		info-kermit@watsun.cc.columbia.edu
+comp.research.japan		japan@cs.arizona.edu
+comp.risks			risks@csl.sri.com
+comp.simulation			simulation@uflorida.cis.ufl.edu
+comp.society			socicom@auvm.american.edu
+comp.society.cu-digest		tk0jut2@mvs.cso.niu.edu
+comp.society.folklore		folklore@snark.thyrsus.com
+comp.society.privacy		comp-privacy@pica.army.mil
+comp.sources.3b1		comp-sources-3b1@galaxia.network23.com
+comp.sources.acorn		cba@acorn.co.nz
+comp.sources.amiga		amiga@uunet.uu.net
+comp.sources.apple2		jac@paul.rutgers.edu
+comp.sources.atari.st		atari-sources@hyperion.com
+comp.sources.games		games@saab.cna.tek.com
+comp.sources.hp48		hp48@seq.uncwil.edu
+comp.sources.mac		macintosh%felix.uucp@uunet.uu.net
+comp.sources.misc		sources-misc@uunet.uu.net
+comp.sources.reviewed		csr@calvin.dgbt.doc.ca
+comp.sources.sun		sun-sources@topaz.rutgers.edu
+comp.sources.unix		unix-sources-moderator@pa.dec.com
+comp.sources.x			x-sources@msi.com
+comp.std.announce		klensin@infoods.mit.edu
+comp.std.mumps			std-mumps@pfcs.com
+comp.std.unix			std-unix@uunet.uu.net
+comp.sys.acorn.announce		announce@acorn.co.uk
+comp.sys.amiga.announce		announce@cs.ucdavis.edu
+comp.sys.amiga.reviews		amiga-reviews-submissions@math.uh.edu
+comp.sys.concurrent		concurrent@bdcsys.suvl.ca.us
+comp.sys.ibm.pc.digest		info-ibmpc@simtel20.army.mil
+comp.sys.m68k.pc		info-68k@ucbvax.berkeley.edu
+comp.sys.mac.announce		csma@rascal.ics.utexas.edu
+comp.sys.mac.digest		info-mac@sumex-aim.stanford.edu
+comp.sys.next.announce		csn-announce@liveware.com
+comp.sys.sun.announce		sun-announce@sunworld.com
+comp.theory.info-retrieval	ir-l%uccvma.bitnet@berkeley.edu
+comp.virus			krvw@cert.org
+comp.windows.x.announce		xannounce@expo.lcs.mit.edu
+misc.activism.progressive	map@pencil.cs.missouri.edu
+misc.handicap			handicap@bunker.shel.isc-br.com
+misc.news.southasia		surekha@nyx.cs.du.edu
+news.admin.technical		natech@zorch.sf-bay.org
+news.announce.conferences	nac@tekbspa.tss.com
+news.announce.important		announce@stargate.com
+news.announce.newgroups		announce-newgroups@rpi.edu
+news.announce.newusers		spaf@cs.purdue.edu
+news.answers			news-answers@mit.edu
+news.lists			news-lists-request@cs.purdue.edu
+news.lists.ps-maps		reid@decwrl.dec.com
+rec.arts.cinema			cinema@zerkalo.harvard.edu
+rec.arts.comics.info		info_comic@dartmouth.edu
+rec.arts.erotica		erotica@telly.on.ca
+rec.arts.movies.reviews		movies@mtgzy.att.com
+rec.arts.sf.announce		sf-announce@zorch.sf-bay.org
+rec.arts.sf.reviews		sf-reviews@presto.ig.com
+rec.arts.startrek.info		trek-info@dweeb.fx.com
+rec.audio.high-end		info-high-audio@csd4.csd.uwm.edu
+rec.food.recipes		recipes@mthvax.cs.miami.edu
+rec.games.cyber			cyberrpg@veritas.com
+rec.games.frp.announce		rg-frp-announce@magnus.acs.ohio-state.edu
+rec.games.frp.archives		frp-archives@rpi.edu
+rec.games.mud.announce		rgm-announce@glia.biostr.washington.edu
+rec.guns			magnum@flubber.cs.umd.edu
+rec.humor.funny			funny@clarinet.com
+rec.humor.oracle		oracle-mod@cs.indiana.edu
+rec.hunting			hunting@osnome.che.wisc.edu
+rec.mag.fsfnet			white@duvm.bitnet
+rec.music.gaffa			love-hounds@uunet.uu.net
+rec.music.info			rec-music-info@ph.tn.tudelft.nl
+rec.music.reviews		music_reviews@sco.com
+rec.radio.broadcasting		rrb@airwaves.chi.il.us
+rec.sport.cricket.scores	cricket@power.eee.ndsu.nodak.edu
+sci.astro.hubble		sah@wfpc3.la.asu.edu
+sci.math.research		sci-math-research@uiuc.edu
+sci.med.aids			aids@cs.ucla.edu
+sci.military			military@att.att.com
+sci.nanotech			nanotech@aramis.rutgers.edu
+sci.psychology.digest		psyc@phoenix.princeton.edu
+sci.space.news			sci-space-news@news.arc.nasa.gov
+sci.virtual-worlds		virtual-worlds@milton.u.washington.edu
+soc.feminism			feminism@ncar.ucar.edu
+soc.politics			poli-sci@rutgers.edu
+soc.politics.arms-d		arms-d@xx.lcs.mit.edu
+soc.religion.bahai		srb@oneworld.wa.com
+soc.religion.christian		christian@aramis.rutgers.edu
+soc.religion.eastern		sre@cse.ogi.edu
+soc.religion.islam		religion-islam@ncar.ucar.edu
+alt.atheism.moderated		atheism@mantis.co.uk
+alt.binaries.pictures.fine-art.d	artcomp@uxa.ecn.bgu.edu
+alt.binaries.pictures.fine-art.digitized	artcomp@uxa.ecn.bgu.edu
+alt.binaries.pictures.fine-art.graphics	artcomp@uxa.ecn.bgu.edu
+alt.comp.acad-freedom.news	caf-news@eff.org
+alt.dev.null			/dev/null
+alt.gourmand			recipes@decwrl.dec.com
+alt.hackers			/dev/null
+alt.hindu			editor@rbhatnagar.csm.uc.edu
+alt.politics.democrats		news-submit@dc.clinton-gore.org
+alt.politics.democrats.clinton	news-submit@dc.clinton-gore.org
+alt.politics.democrats.governors	news-submit@dc.clinton-gore.org
+alt.politics.democrats.house	news-submit@dc.clinton-gore.org
+alt.politics.democrats.senate	news-submit@dc.clinton-gore.org
+alt.security.index		kyle@uunet.uu.net
+alt.society.ati			gzero@tronsbox.xei.com
+alt.society.cu-digest		tk0jut2@mvs.cso.niu.edu
+alt.sources.index		kyle@uunet.uu.net
+austin.eff			eff-austin-moderator@tic.com
+ba.announce			ba-announce@zorch.sf-bay.org
+bionet.announce			biosci-announce-moderator@genbank.bio.net
+bionet.biology.computational	comp-bio-moderator@genbank.bio.net
+bionet.molbio.ddbj.updates	ddbj-updates@genbank.bio.net
+bionet.molbio.embldatabank.updates	embl-updates@genbank.bio.net
+bionet.molbio.genbank.updates	lear@genbank.bio.net
+bionet.software.sources		software-sources@genbank.bio.net
+bit.listserv.big-lan		big-req@suvm.acs.syr.edu
+bit.listserv.edtech		21765EDT%MSU@CUNYVM.CUNY.EDU
+bit.listserv.gaynet		gaynet@athena.mit.edu
+bit.listserv.hellas		sda106@psuvm.psu.edu
+bit.listserv.l-hcap		wtm@bunker.shel.isc-br.com
+bit.listserv.libres		librk329@KentVMS.Kent.edu
+bit.listserv.new-list		NU021172@VM1.NoDak.EDU
+bit.listserv.pacs-l		LIBPACS%UHUPVM1@CUNYVM.CUNY.EDU
+bit.listserv.valert-l		krvw@cert.org
+biz.dec.decnews			decnews@mr4dec.enet.dec.com
+biz.sco.announce		scoannmod@xenitec.on.ca
+biz.sco.binaries		sl@wimsey.bc.ca
+biz.sco.sources			kd1hz@anomaly.sbs.risc.net
+biz.zeos.announce		kgermann@zeos.com
+can.canet.d			canet-d@canet.ca
+can.uucp.maps			pathadmin@cs.toronto.edu
+comp.protocols.iso.x400.gateway	ifip-gtwy-usenet@ics.uci.edu
+comp.security.announce		cert@cert.org
+ddn.mgt-bulletin		nic@nic.ddn.mil
+ddn.newsletter			nic@nic.ddn.mil
+de.admin.lists			de-admin-lists@hactar.hanse.de
+de.admin.submaps		maps@flatlin.ka.sub.org
+de.comp.sources.amiga		agnus@amylnd.stgt.sub.org
+de.comp.sources.misc		sources@watzman.quest.sub.org
+de.comp.sources.os9		fkk@stasys.sta.sub.org
+de.comp.sources.st		sources-st@watzman.quest.sub.org
+de.comp.sources.unix		de-comp-sources-unix@germany.sun.com
+de.mag.chalisti			ccc@sol.ccc.de
+de.newusers			newusers@jattmp.nbg.sub.org
+de.org.dfn			org-dfn@dfn.de
+de.org.eunet			news@germany.eu.net
+de.org.sub			vorstand@smurf.sub.org
+de.sci.ki			hein@damon.irf.uni-dortmund.de
+de.sci.ki.mod.ki		hein@damon.irf.uni-dortmund.de
+fj.announce			fj-announce@junet.ad.jp
+fj.binaries			fj-binaries@junet.ad.jp
+fj.binaries.x68000		fj-binaries-x68000@junet.ad.jp
+fj.guide.admin			fj-guide-admin@junet.ad.jp
+fj.guide.general		fj-guide-general@junet.ad.jp
+fj.guide.newusers		fj-guide-newusers@junet.ad.jp
+fj.map				fj-map@junet.ad.jp
+gnu.announce			info-gnu@prep.ai.mit.edu
+gnu.bash.bug			bug-bash@prep.ai.mit.edu
+gnu.emacs.announce		info-gnu-emacs@prep.ai.mit.edu
+gnu.emacs.bug			bug-gnu-emacs@prep.ai.mit.edu
+gnu.g++.announce		info-g++@prep.ai.mit.edu
+gnu.g++.bug			bug-g++@prep.ai.mit.edu
+gnu.g++.lib.bug			bug-lib-g++@prep.ai.mit.edu
+gnu.gcc.announce		info-gcc@prep.ai.mit.edu
+gnu.gcc.bug			bug-gcc@prep.ai.mit.edu
+gnu.gdb.bug			bug-gdb@prep.ai.mit.edu
+gnu.ghostscript.bug		bug-ghostscript@prep.ai.mit.edu
+gnu.groff.bug			bug-groff@prep.ai.mit.edu
+gnu.smalltalk.bug		bug-gnu-smalltalk@prep.ai.mit.edu
+gnu.utils.bug			bug-gnu-utils@prep.ai.mit.edu
+houston.weather			weather-monitor@tmc.edu
+ieee.tcos			tcos@cse.ucsc.edu
+info.academic.freedom		caf-talk@eff.org
+info.admin			usenet@ux1.cso.uiuc.edu
+info.bind			bind@arpa.berkeley.edu
+info.brl.cad			cad@brl.mil
+info.bytecounters		bytecounters@venera.isi.edu
+info.cmu.tek.tcp		cmu-tek-tcp@cs.cmu.edu
+info.convex			info-convex@pemrac.space.swri.edu
+info.firearms			firearms@cs.cmu.edu
+info.firearms.politics		firearms-politics@cs.cmu.edu
+info.gated			gated-people@devvax.tn.cornell.edu
+info.ietf			ietf@venera.isi.edu
+info.ietf.hosts			ietf-hosts@nnsc.nsf.net
+info.ietf.isoc			isoc-interest@relay.sgi.com
+info.ietf.njm			njm@merit.edu
+info.ietf.smtp			ietf-smtp@dimacs.rutgers.edu
+info.isode			isode@nic.ddn.mil
+info.jethro.tull		jtull@remus.rutgers.edu
+info.labmgr			labmgr@ukcc.uky.edu
+info.mach			info-mach@cs.cmu.edu
+info.mh.workers			mh-workers@ics.uci.edu
+info.nets			info-nets@think.com
+info.nsf.grants			grants@note.nsf.gov
+info.nsfnet.cert		nsfnet-cert@merit.edu
+info.nysersnmp			nysersnmp@nisc.nyser.net
+info.osf			roma@uiuc.edu
+info.pem.dev			pem-dev@tis.com
+info.ph				info-ph@uxc.cso.uiuc.edu
+info.rfc			rfc-request@nic.ddn.mil
+info.snmp			snmp@nisc.nyser.net
+info.sun.managers		sun-managers@rice.edu
+info.sun.nets			sun-nets@umiacs.umd.edu
+info.theorynt			theorynt@vm1.nodak.edu
+info.unix.sw			unix-sw-request@wsmr-simtel20.army.mil
+mi.map				uucpmap@rel.mi.org
+opinions.supreme-court		opinions@uunet.uu.net
+relcom.infomarket.quote		relcom-infomarket-quote@news.ussr.eu.net
+relcom.infomarket.talk		relcom-infomarket-talk@news.ussr.eu.net
+relcom.jusinf			relcom-jusinf@news.ussr.eu.net
+relcom.postmasters		relcom-postmasters@news.ussr.eu.net
+relcom.renews			relcom-renews@news.ussr.eu.net
+resif.oracle			oracle@grasp1.univ-lyon1.fr
+sfnet.atk.flpf.tiedotukset	flpf@nic.funet.fi
+sfnet.csc.tiedotukset		netmgr@csc.fi
+sfnet.funet.tiedotukset		toimitus@funet.fi
+sfnet.fuug.tiedotukset		sfnet-fuug-tiedotukset@fuug.fi
+sfnet.harrastus.astronomia	pvtmakela@cc.helsinki.fi
+sfnet.harrastus.mensa		jau@cs.tut.fi
+sfnet.lists.sunflash		flash@sunvice.East.Sun.COM
+sfnet.opiskelu.ymp.kurssit	hoffren@cc.Helsinki.FI
+sfnet.tiede.tilastotiede.jatkokoulutus	til_tied@cc.helsinki.fi
+sura.announce			sura-announce@darwin.sura.net
+sura.noc.status			sura-noc-status@darwin.sura.net
+sura.security			sura-security@darwin.sura.net
+tamu.religion.christian		shetler@eemips.tamu.edu
+tx-thenet-managers		themgr-moderator@nic.the.net
+tx.maps				texas-uucpmaps@tmc.edu
+uiuc.org.men			uiuc-men-ml@ux1.cso.uiuc.edu
+uunet.alternet			asp@uunet.uu.net,postman@uunet.uu.net
+uunet.announce			postman@uunet.uu.net
+uunet.products			postman@uunet.uu.net
+uunet.status			postman@uunet.uu.net
+uunet.tech			postman@uunet.uu.net
+vmsnet.announce			vmsnet-announce@mccall.com
+vmsnet.announce.newusers	vmsnet-announce-newusers@mccall.com
+vmsnet.sources			vmsnet-sources@mvb.saic.com
diff --git a/decus/vmslt98a/bulletin/news.txt b/decus/vmslt98a/bulletin/news.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1117dc62d8e1b34664938b7916c5fe133e7ec02d
--- /dev/null
+++ b/decus/vmslt98a/bulletin/news.txt
@@ -0,0 +1,150 @@
+BULLETIN now has the capability to read and post messages to USENET NEWS in a
+client mode.  I realize that there are many NEWS readers, some with much more
+elegant interfaces.  However, I elected to modify BULLETIN for the following
+reason:  We have many decnet nodes, but only several are internet nodes.  Our
+only access to a news server was via internet.  In order for those
+non-internet nodes to read USENET, the only method that seemed available was to
+run a NEWS server program on one of our own internet nodes so that it could
+be accessible via decnet.  I did not want to do that, as that requires storing
+the news groups on disk, and I do not have the room for that.  I thus added the
+ability in BULLETIN (actually BULLCP) so that it acts as as a gateway between
+decnet and tcp for NEWS.  This method does not require spawning any processes,
+since the detached process BULLCP is always present, so the access is very
+fast.  Also, since BULLETIN uses a shared database to store info on the NEWS
+groups and periodically updates it, there is no need for that to be done when a
+user accesses the NEWS groups.  Several other NEWS readers do this when you run
+them, which is why they take a long time to start up.  It is also possible to
+feed NEWS groups into a "real" BULLETIN folder, so that the messages are saved
+on disk.
+
+Presently, BULLETIN can be used with either UCX, MULTINET, or CMU TCP/IP
+packages (and of course DECNET) for reading NEWS.  Support for other packages
+can be added if I can find sites willing to beta test the interface for me. 
+The source for the TCP interface is in C rather than FORTRAN because the
+MULTINET include files are in C. However, if you do not have C, I will be glad
+to send the object for it (or to even possibly rewrite the code in FORTRAN). 
+
+The instructions for installation are as follows.  Define BULL_NEWS_SERVER
+to be a system logical name pointing to either your internet or decnet NEWS
+node.  If it is decnet, simply specify the decnet node name, i.e.
+
+	$ DEFINE/SYSTEM BULL_NEWS_SERVER NERUS
+
+BULLETIN decides to use DECNET rather than TCP access based on the node name.
+If it does not have any periods in it, then it assumes it is a DECNET node.
+
+In our cluster, we usually have one node which is an internet node, and the
+rest non-internet nodes.  If you have a similar situation, you'll have to
+create a startup procedure that defines BULL_NEWS_SERVER to be the internet
+news server address only on the node (or nodes) on the cluster that have
+actually internet access.  The other nodes will have BULL_NEWS_SERVER defined
+as the decnet node name that BULLCP is running on in the cluster.  (Of course,
+BULLCP will have to be running on a node with internet access.)
+
+NOTE: If you want to disable the gateway feature, then before starting BULLCP,
+define the logical name:
+
+	$ DEFINE/SYSTEM BULL_NO_NEWS_GATEWAY "TRUE"
+
+Defining this will only shut off the gateway.  BULLETIN will still be allowed
+to read NEWS from the local node as long as BULL_NEWS_SERVER is defined.
+
+You can also specify that BULLCP is only to act as a NEWS gateway.  This is to
+allow adding the news gateway to an INTERNET site that you have DECNET access
+to, but which does not want to make use of any of the other BULLETIN features.
+You would specify the following command before starting BULLCP:
+
+	$ DEFINE/SYSTEM BULL_NEWS_GATEWAY_ONLY "TRUE"
+
+In order to post messages, BULLETIN needs to know the internet nodename of
+the local host.  This is done automatically for nodes running MULTINET.  For
+other nodes, BULLETIN attempts to translate the logical name ARPANET_HOST_NAME,
+INTERNET_HOST_NAME, and MX_NODE_NAME.  If you are on a DECNET node that is not
+on INTERNET (and is not part of a cluster which has an INTERNET address), but
+you are accessing NEWS via DECNET, you can specify the hostname as follows:
+
+     $ DEFINE/SYSTEM INTERNET_HOST_NAME "%localhost@internet-address"
+
+Where "localhost" is your local decnet hostname, and "internet-address" is the
+internet address of the gateway node.
+
+The local time zone is detected by looking at the following logical names:
+LISP$TIME_ZONE, MULTINET_TIMEZONE, or PMDF_TIMEZONE.  (LISP$TIME_ZONE is
+defined if you have LISP installed.)
+
+The name of the organization is included in the header of the NEWS message.
+This can be anything, but usually is the company or university name.  This
+can be hardcoded into the source by putting in BULLNEWS.INC, or by defining
+the system logical name BULL_NEWS_ORGANIZATION.
+
+The name of the mail protocol to use for responding by mail to NEWS messages
+can also be either hardcoded by putting in BULLNEWS.INC, or by defining the
+system logical name BULL_NEWS_MAILER.
+
+After installing the new BULLETIN, execute the command NEWS, which asks for a
+list of all the news groups.  Because this is the first time it is executed, it
+will cause a load of all the remote news groups into a local data base
+(BULL_DIR:BULLNEWS.DAT). This will take several minutes to do.  It is the only
+time that this load will be done interactively.  Afterwards, BULLCP will
+periodically update the data base.  For this reason, it is highly recommeded
+that BULLCP be installed. BULLCP will update NEWS every hour.  If you want to
+change this frequency, define the logical name BULL_NEWS_UPDATE to the number
+of minutes in between updates, i.e. DEFINE/SYSTEM BULL_NEWS_UPDATE "30" for 30
+minutes.  NOTE: BULLCP will create a subprocess BULLCP NEWS which does the
+update.  You can watch how long it takes for this to run in order to determine
+if you want to change the update period).
+
+Due to long news group names recently created, you must do the following, or
+else those news groups will not be seen.  After BULLNEWS.DAT is created, do
+the following:
+
+$ ANAL/RMS/FDL/OUT=FIX.FDL BULL_DIR:BULLNEWS.DAT
+
+Edit FIX.FDL and find the first line which says
+	DUPLICATES no
+and change it to
+	DUPLICATES yes
+
+Then type:
+
+$ CONVERT BULL_DIR:BULLNEWS.DAT BULL_DIR:BULLNEWS.DAT/FDL=FIX.FDL
+
+Also, it is suggested that you run OPTIMIZE_RMS.COM on it, as it will cause the
+file to be compressed and will allow updates to run much faster (factor of 5 or
+more). 
+
+Never delete BULLNEWS.DAT.  There is no reason to ever do so, and it will cause
+subscribed users to be subscribed to the wrong news groups.
+
+WARNING: One user discovered that his server (using bnews?) had a bug which
+caused the updates to cause bogus "new messages" notifications for subscribed
+NEWS group when entering BULLETIN.  If you experience this problem, try
+defining the system logical name BULL_SPECIAL_NEWS_UPDATE.  This will cause
+the update to use a different algorithm which should eliminate the problem,
+although it requires much more time to execute.
+
+It is possible to automatically have news messages to be fed into a real
+folder. Place the name of the news group into the folder description surrounded
+by <>, i.e. <misc.test>.  It must be in lower case.  (Other text is allowed in
+the description, i.e. "THIS IS A TEST FOLDER <misc.test>".)  When the POST and
+ADD commands are used with this folder, the messages will be posted to the news
+group, rather than actually being added to the folder.
+
+If you have any problems or questions, please let me know.
+									MRL
+P.s.
+	If you do not know what USENET NEWS, it's basically news messages which
+are passed between nodes.  Originally it was limited to USENET, but that is no
+longer the case.  Unlike internet mailing lists which use MAIL to send the
+messages to individuals, NEWS messages are not sent via MAIL.  They are passed
+between nodes using a special protocol, NNTP.  Users must use a NEWS reader
+package to read them.  However, it is possible to read NEWS remotely over a
+network, and therefore avoiding having to actually store the messages.
+BULLETIN is setup to be used mainly in this client mode, i.e. it can read
+messages on another node via TCP or DECNET.  This is useful, since the number
+of NEWS groups total over 1000, the disk space required for storage is very
+high.  If you are interested in finding a server node that would allow you to
+read NEWS, and do not know of one (i.e. a USENET node), I know of no official
+way of doing so.  However, one suggestion was to try connecting to BBN.COM via
+ANONYMOUS FTP and look through the directory uumap/comp.mail.maps to find a
+USENET node near you to contact. 
diff --git a/decus/vmslt98a/bulletin/nonsystem.txt b/decus/vmslt98a/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..f1f7d86296699f21a3ed0b944452230a6ccce18a
--- /dev/null
+++ b/decus/vmslt98a/bulletin/nonsystem.txt
@@ -0,0 +1,16 @@
+Non-system bulletins (such as this) can be submitted by any user.  Users are
+alerted at login time that new non-system bulletins have been added, but only
+their topics are listed.  Optionally, users can be prompted at login time to
+see if they wish to read the bulletins.  When reading the bulletins in this
+manner, the bulletins can optionally be written to a file.  If you have the
+subdirectory [.BULL] created, BULLETIN will use that directory as the default
+directory to write the file into.
+
+A user can disable this prompting featuring by using BULLETIN as follows: 
+
+$ BULLETIN
+BULLETIN> SET NOREADNEW
+BULLETIN> EXIT
+
+Afterwords, the user will only be alerted of the bulletins, and will have to
+use the BULLETIN utility in order to read the messages.
diff --git a/decus/vmslt98a/bulletin/optimize_rms.com b/decus/vmslt98a/bulletin/optimize_rms.com
new file mode 100755
index 0000000000000000000000000000000000000000..576fa3e106bdd1b01865b9bd84ac1e8d15a0c209
--- /dev/null
+++ b/decus/vmslt98a/bulletin/optimize_rms.com
@@ -0,0 +1,134 @@
+$ SET NOON
+$ EXIT_STATUS = 1
+$ IF P1 .NES. "" THEN GOTO BATCH
+$!
+$GET_FILE:
+$ INQUIRE P1 "File to be optimized (^Y to quit)"
+$!
+$ FILENAME = P1
+$ SPEC = F$SEARCH(FILENAME)
+$!
+$GOT_NAME_INTERACTIVE:
+$ NAME = F$PARSE(FILENAME,,,"NAME")
+$!
+$ IF F$FILE_ATTRIBUTE(FILENAME,"ORG") .EQS. "IDX" THEN-
+  GOTO INTERACTIVE_CHECK_ADDS
+$ WRITE SYS$OUTPUT "File not indexed"
+$ GOTO GET_FILE
+$INTERACTIVE_CHECK_ADDS:
+$ INQUIRE P2 "Number of records to add after initial load"
+$ IF P2 .EQS. "" THEN P2 = 0
+$!
+$ IF P2 .GE. 0 THEN GOTO INTERACTIVE_CHECK_CONVERT
+$ WRITE SYS$OUTPUT "Added records must be >= 0 "
+$ GOTO GOT_NAME_INTERACTIVE
+$!
+$INTERACTIVE_CHECK_CONVERT:
+$ INQUIRE P3 "Turn OFF Data and Key compression? (N)"
+$ INQUIRE P4 "Turn OFF Index compression? (N)"
+$!
+$ GOTO ADD_OK
+$!
+$BATCH:
+$GOT_NAME:
+$ FILENAME = P1
+$ SPEC = F$SEARCH(FILENAME)
+$!
+$ IF SPEC .NES. "" THEN GOTO FILE_EXISTS
+$ WRITE SYS$OUTPUT "File does not exist"
+$ EXIT_STATUS = %X18292
+$ GOTO DONE
+$!
+$FILE_EXISTS:
+$ NAME = F$PARSE(FILENAME,,,"NAME")
+$ IF F$FILE_ATTRIBUTE(FILENAME,"ORG") .EQS. "IDX" THEN-
+  GOTO TYPE_OK
+$ WRITE SYS$OUTPUT "File not indexed"
+$ EXIT_STATUS = 1000024
+$ GOTO DONE
+$!
+$TYPE_OK:
+$ IF P2 .EQS. "" THEN P2 = 0
+$ IF P2 .GE. 0 THEN GOTO ADD_OK
+$!
+$ WRITE SYS$OUTPUT "Added records must be >= 0 "
+$ EXIT_STATUS = %X38060
+$ GOTO DONE
+$!
+$ADD_OK:
+$ ADD_RECORDS = P2
+$!
+$ NUMBER_OF_KEYS == 'F$FILE_ATTRIBUTE(FILENAME,"NOK")
+$ TURN_DATA_COMPRESSION_OFF = P3
+$ TURN_INDEX_COMPRESSION_OFF = "Y"
+$ FDL_NAME = F$PARSE(".FDL;0",SPEC)
+$ TEMP_FILE = "''NAME'_TEMP_TEMP.COM"
+$ OPEN/WRITE/ERROR=OPEN_ERROR OUT 'TEMP_FILE
+$ WRITE OUT "$ DEFINE/USER SYS$COMMAND SYS$INPUT"
+$ WRITE OUT "$ ANALYZE/RMS/FDL/OUT=''FDL_NAME' ''FILENAME'"
+$ WRITE OUT "$ DEFINE/USER SYS$COMMAND SYS$INPUT"
+$ WRITE OUT "$ DEFINE/USER EDF$$PLAYBACK_INPUT KLUDGE"
+$ WRITE OUT "$ EDIT/FDL/SCRIPT=OPTIMIZE/ANALYZE=''FDL_NAME' ''FDL_NAME'"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT 'ADD_RECORDS
+$ IF ADD_RECORDS .EQ. 0 THEN GOTO SKIP_NON_ZERO
+$ WRITE OUT ""
+$ WRITE OUT ""
+$SKIP_NON_ZERO:
+$ WRITE OUT ""
+$ IF TURN_INDEX_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "IC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ IF TURN_DATA_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "RC"
+$  WRITE OUT "NO"
+$  WRITE OUT "KC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ WRITE OUT "FD"
+$ WRITE OUT "Created from OPTIMIZE_RMS.COM, WITH SPACE/BUCKETSIZE for" +-
+  " ''A DD_RECORDS' ADDED RECORDS"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$LOOP:
+$ IF NUMBER_OF_KEYS .EQ. 1 THEN GOTO CLOSE_FILE
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ IF TURN_INDEX_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "IC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ IF TURN_DATA_COMPRESSION_OFF
+$ THEN
+$  WRITE OUT "KC"
+$  WRITE OUT "NO"
+$ ENDIF
+$ WRITE OUT "FD"
+$ WRITE OUT ""
+$ WRITE OUT ""
+$ NUMBER_OF_KEYS = 'NUMBER_OF_KEYS - 1
+$ GOTO LOOP
+$!
+$CLOSE_FILE:
+$ WRITE OUT "E"
+$ CLOSE OUT
+$!
+$ @'TEMP_FILE
+$ DELETE 'TEMP_FILE;*
+$ WRITE SYS$OUTPUT ""
+$ WRITE SYS$OUTPUT "Starting CONVERT of ''FILENAME'"
+$ CONVERT /NOSORT /STAT /FDL='FDL_NAME 'FILENAME 'FILENAME
+$ WRITE SYS$OUTPUT ""
+$ GOTO DONE
+$OPEN_ERROR:
+$ WRITE SYS$OUTPUT "Unable to open ''TEMP_FILE'"
+$DONE:
+$ EXIT 'EXIT_STATUS
diff --git a/decus/vmslt98a/bulletin/pmdf.com b/decus/vmslt98a/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..932715cb6815af4f9035a39a69e622c8494ade2c
--- /dev/null
+++ b/decus/vmslt98a/bulletin/pmdf.com
@@ -0,0 +1,1031 @@
+$set nover
+$copy/log sys$input BULLETIN_MASTER.PAS
+$deck
+%INCLUDE 'PMDF_ROOT:[SRC]ATTRIB.INC'
+PROGRAM bulletin_master (output, outbound,
+                         %INCLUDE 'PMDF_ROOT:[SRC]APFILES.INC',
+                         %INCLUDE 'PMDF_ROOT:[SRC]MMFILES.INC',
+                         %INCLUDE 'PMDF_ROOT:[SRC]QUFILES.INC');
+
+(*******************************************************************)
+(*                                                                 *)
+(*      Authors:   Ned Freed (ned@ymir.bitnet)                     *)
+(*                 Mark London (mrl%mit.mfenet@nmfecc.arpa)        *)
+(*                 8/18/88                                         *)
+(*                                                                 *)
+(*******************************************************************)
+
+  CONST
+       %INCLUDE 'PMDF_ROOT:[SRC]UTILCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]OSCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]APCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]MMCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]HECONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]LOGCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]SYCONST.INC'
+
+  TYPE
+       %INCLUDE 'PMDF_ROOT:[SRC]UTILTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]OSTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]APTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]SYTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]MMTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]HETYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]LOGTYPE.INC'
+
+  string = varying [alfa_size] of char;
+
+  VAR
+       %INCLUDE 'PMDF_ROOT:[SRC]UTILVAR.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]OSVAR.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]APVAR.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]QUVAR.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]MMVAR.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]HEVAR.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]LOGVAR.INC'
+
+       outbound : text;
+
+  (* Place to store the channel we are servicing *)
+   mail_channel : mm_channel_ptr := nil;
+
+  (* MM status control flag *)
+
+  mm_status          : (uninitialized, initialized, sending) := uninitialized;
+
+  filename       : vstring;
+
+  (* Place to store the protocol that we are providing/servicing *)
+  protocol_name : varying [10] of char;
+
+  %INCLUDE 'PMDF_ROOT:[SRC]UTILDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]OSDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]APDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]HEDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]LOGDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]MMDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]QUDEF.INC'
+
+  (* Declare interface routines to BULLETIN *)
+
+  procedure INIT_MESSAGE_ADD (
+    in_folder : [class_s] packed array [l1..u1 : integer] of char;
+    in_from : [class_s] packed array [l2..u2 : integer] of char;
+    in_descrip : [class_s] packed array [l3..u3 : integer] of char;
+    var ier : boolean); extern;
+
+  procedure WRITE_MESSAGE_LINE (
+    in_line : [class_s] packed array [l1..u1 : integer] of char); extern;
+
+  procedure FINISH_MESSAGE_ADD; extern;
+
+  PROCEDURE warn_master (message : varying [len1] of char);
+
+    BEGIN (* warn_master *)
+      writeln;
+      os_write_datetime (output);
+      writeln (message);
+      END; (* warn_master *)
+
+  (* abort program. *)
+
+  PROCEDURE abort_master (message : varying [len1] of char);
+
+    BEGIN (* abort_master *)
+      warn_master (message);
+      halt;
+      END; (* abort_master *)
+
+(* activate_mm fires up the MM package and performs related startup chores. *)
+
+function activate_mm (is_master : boolean) : rp_replyval;
+
+var
+  mm_init_reply : rp_replyval; found : boolean; mail_chan_text : ch_chancode;
+  stat : integer;
+
+begin (* activate_mm *)
+  (* Set up the name of the protocol we are servicing/providing *)
+  stat := $TRNLOG (lognam := 'PMDF_PROTOCOL',
+                   rslbuf := protocol_name.body,
+                   rsllen := protocol_name.length);
+  if (not odd (stat)) or (stat = SS$_NOTRAN) then protocol_name := 'IN%';
+  mm_status := initialized;
+  mm_init_reply := mm_init;
+  mail_chan_text := '            ';
+  stat := $TRNLOG (lognam := 'PMDF_CHANNEL', rslbuf := mail_chan_text);
+  if (not odd (stat)) or (stat = SS$_NOTRAN) then
+    mail_chan_text := 'l           ';
+  if rp_isgood (mm_init_reply) then begin
+    mail_channel := mm_lookup_channel (mail_chan_text);
+    if mail_channel = nil then mail_channel := mm_local_channel;
+  end else mail_channel := mm_local_channel;
+  activate_mm := mm_init_reply;
+end; (* activate_mm *)
+
+  (* initialize outbound, mm_ and qu_ *)
+
+  PROCEDURE init;
+
+    VAR fnam : vstring;
+        i : integer;
+
+    BEGIN (* init *)
+      os_jacket_access := true;
+      (* Initialize subroutine packages *)
+      IF rp_isbad (activate_mm (false)) THEN
+        abort_master ('Can''t initialize MM_ routines');
+      IF rp_isbad (qu_init) THEN
+        abort_master ('Can''t initialize QU_ routines');
+      fnam.length := 0;
+      IF NOT os_open_file (outbound, fnam, exclusive_read) THEN
+        abort_master ('Can''t open outbound file');
+      END; (* init *)
+
+
+procedure return_bad_messages (var bad_address : vstring);
+
+label
+  100;
+
+var
+  line : vstring;
+  bigline : bigvstring; result : rp_bufstruct;
+  pmdfenvelopefrom : vstring;
+  temp_line : vstringlptr;
+
+  procedure try_something (rp_error : integer; routine : string);
+
+  begin (* try_something *)
+    if rp_isbad (rp_error) then begin
+      mm_wkill; mm_status := initialized; goto 100;
+    end;
+  end; (* try_something *)
+
+begin (* return_bad_messages *)
+  if mm_status = uninitialized then
+    try_something (activate_mm (false), 'mm_init');
+  mm_status := sending;
+  try_something (mm_sbinit, 'mm_sbinit');
+  initstring (line, 'postmaster@                             ', 11);
+  catvstring (line, mm_local_channel^.official_hostname);
+  try_something (mm_winit (mail_channel^.chancode, line), 'mm_winit');
+  initstring (line,
+              'postmaster                              ', 10);
+  try_something (mm_wadr (mail_channel^.official_hostname,
+                            line), 'mm_wadr');
+  try_something (mm_rrply (result), 'mm_rrply');
+  try_something (result.rp_val, 'mm_rrply structure return');
+  try_something (mm_waend, 'mm_waend');
+  initstring (line, 'From: PMDF Mail Server <Postmaster@     ', 35);
+  catvstring (line, mm_local_channel^.official_hostname);
+  catchar (line, '>');
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  initstring (line, 'To: Postmaster                          ', 14);
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  initstring (line, 'Subject: Undeliverable mail             ', 27);
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  initstring (line, 'Date:                                   ', 6);
+  os_cnvtdate (line);
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  line.length := 1; line.body[1] := chr (chr_lf);
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  initstring (line, 'The message could not be delivered to:  ', 38);
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  line.length := 1; line.body[1] := chr (chr_lf);
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  initstring (line, 'Addressee:                              ', 11);
+  catvstring (line, bad_address);
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  initstring (line, 'Reason: No such bulletin folder.        ', 32);
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  line.length := 1; line.body[1] := chr (chr_lf);
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  initstring (line, '----------------------------------------', 40);
+  catchar (line, chr (chr_lf));
+  catchar (line, chr (chr_lf));
+  try_something (mm_wtxt (line), 'mm_wtxt');
+  try_something (qu_rkill, 'qu_rkill');
+  try_something (qu_rinit (filename, pmdfenvelopefrom), 'qu_rinit');
+  while rp_isgood (qu_radr (line)) do begin end;
+  while rp_isgood (qu_rtxt (bigline)) do
+    try_something (mm_bigwtxt (bigline), 'mm_wtxt');
+  mm_status := initialized;
+  try_something (mm_wtend, 'mm_wtend');
+  try_something (mm_rrply (result), 'mm_rrply');
+  try_something (result.rp_val, 'mm_rrply structure return');
+100:
+end; (* return_bad_messages *)
+
+  (* submit messages to BULLETIN *)
+
+  PROCEDURE dosubmit;
+
+    VAR fromaddr, toaddr, tombox, name : vstring;
+        retval : rp_replyval;
+        line : bigvstring;
+        ier, done : boolean;
+        i : integer;
+
+    BEGIN (* dosubmit *)
+      WHILE NOT eof (outbound) DO BEGIN
+        readvstring (outbound, filename, 0);
+        IF rp_isgood (qu_rinit (filename, fromaddr)) THEN BEGIN
+          done := false;
+          FOR i := 1 TO fromaddr.length DO
+            fromaddr.body[i] := upper_case (fromaddr.body[i]);
+          IF rp_isgood (qu_radr (toaddr)) THEN BEGIN
+            REPEAT
+              retval := qu_radr (name);
+              UNTIL rp_isbad (retval);
+            mm_parse_address (toaddr, name, tombox, TRUE, FALSE, 0);
+            FOR i := 1 TO tombox.length DO
+              tombox.body[i] := upper_case (tombox.body[i]);
+            INIT_MESSAGE_ADD (substr (tombox.body, 1, tombox.length),
+                              protocol_name,' ', ier);
+(* The parameter with 'IN%', causes bulletin to search for the From line: *)
+(*                            substr (fromaddr.body, 1, fromaddr.length), *)
+            IF ier THEN BEGIN
+              WHILE rp_isgood (qu_rtxt (line)) DO BEGIN
+                IF line.length > 0 THEN line.length := pred (line.length);
+                WRITE_MESSAGE_LINE (substr (line.body, 1, line.length));
+                END; (* while *)
+              FINISH_MESSAGE_ADD;
+              done := true;
+            END ELSE BEGIN
+	      warn_master ('Error opening folder ' +
+                              substr (tombox.body, 1, tombox.length));
+	      return_bad_messages(tombox);
+              done := true;
+            END;
+	  END
+          ELSE warn_master ('Can''t read To: address in file ' +
+                            substr (filename.body, 1, filename.length));
+          if done then qu_rend else qu_rkill;
+          END
+        ELSE warn_master ('Can''t open queue file ' +
+                          substr (filename.body, 1, filename.length));
+        END; (* while *)
+      END; (* dosubmit *)
+
+  BEGIN (* bulletin_master *)
+    init;
+    dosubmit;
+    mm_end (true);
+    qu_end;
+    END. (* bulletin_master *)
+$eod 
+$copy/log sys$input BULLETIN_MASTER.PAS_V32
+$deck
+%INCLUDE 'PMDF_ROOT:[SRC]ATTRIB.INC'
+PROGRAM bulletin_master (%INCLUDE 'PMDF_ROOT:[SRC]APFILES.INC'
+                         %INCLUDE 'PMDF_ROOT:[SRC]MMFILES.INC'
+                         %INCLUDE 'PMDF_ROOT:[SRC]QUFILES.INC'
+                         outbound);
+     
+(*******************************************************************)
+(*                                                                 *)
+(*      Authors:   Ned Freed (ned@ymir.claremont.edu)              *)
+(*                 Mark London (mrl@nerus.pfc.mit.edu)             *)
+(*                 12/28/90                                        *)
+(*                                                                 *)
+(*******************************************************************)
+     
+  CONST
+       %INCLUDE 'PMDF_ROOT:[SRC]UTILCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]OSCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]APCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]SYCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]HECONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]MMCONST.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]LOGCONST.INC'
+     
+  TYPE
+       %INCLUDE 'PMDF_ROOT:[SRC]UTILTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]OSTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]APTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]SYTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]HETYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]MMTYPE.INC'
+       %INCLUDE 'PMDF_ROOT:[SRC]LOGTYPE.INC'
+
+  string = varying [alfa_size] of char;
+
+  VAR
+(*     %INCLUDE 'PMDF_ROOT:[SRC]UTILVAR.INC' *)
+       %INCLUDE 'PMDF_ROOT:[SRC]OSVAR.INC'
+(*     %INCLUDE 'PMDF_ROOT:[SRC]APVAR.INC' *)
+(*     %INCLUDE 'PMDF_ROOT:[SRC]QUVAR.INC' *)
+       %INCLUDE 'PMDF_ROOT:[SRC]MMVAR.INC'
+(*     %INCLUDE 'PMDF_ROOT:[SRC]HEVAR.INC' *)
+(*     %INCLUDE 'PMDF_ROOT:[SRC]LOGVAR.INC' *)
+     
+       outbound : text;
+       fromaddr, filename : vstring;
+       bull_chan : mm_channel_ptr;
+       bull_chan_text : ch_chancode;
+       protocol_name : varying [10] of char;
+
+  %INCLUDE 'PMDF_ROOT:[SRC]UTILDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]OSDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]APDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]HEDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]LOGDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]SYDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]MMDEF.INC'
+  %INCLUDE 'PMDF_ROOT:[SRC]QUDEF.INC'
+     
+  (* Declare interface routines to BULLETIN *)
+     
+  procedure INIT_MESSAGE_ADD (
+    in_folder : [class_s] packed array [l1..u1 : integer] of char;
+    in_from : [class_s] packed array [l2..u2 : integer] of char;
+    in_descrip : [class_s] packed array [l3..u3 : integer] of char;
+    var ier : boolean); extern;
+     
+  procedure WRITE_MESSAGE_LINE (
+    in_line : [class_s] packed array [l1..u1 : integer] of char); extern;
+     
+  procedure FINISH_MESSAGE_ADD; extern;
+     
+  PROCEDURE warn_master (message : varying [len1] of char);
+     
+    BEGIN (* warn_master *)
+      writeln (os_output_file^);
+      os_write_datetime (os_output_file^);
+      writeln (os_output_file^, message);
+      END; (* warn_master *)
+     
+  (* initialize outbound, mm_ and qu_ *)
+     
+  PROCEDURE init;
+     
+    VAR fnam : vstring;
+        i, stat : integer;
+
+    BEGIN (* init *)
+      os_insure_open_output;
+      os_jacket_access := true;
+      (* Initialize subroutine packages *)
+      IF rp_isbad (mm_init) THEN
+        mm_abort_program (os_output_file^,
+          'Can''t initialize MM_                    ', 20, true);
+      IF rp_isbad (qu_init) THEN
+        mm_abort_program (os_output_file^,
+          'Can''t initialize QU_                    ', 20, false);
+      bull_chan := mm_my_channel (bull_chan_text);
+      (* Set up the name of the protocol we are servicing/providing *)
+      stat := $TRNLOG (lognam := 'PMDF_PROTOCOL',
+                       rslbuf := protocol_name.body,
+                       rsllen := protocol_name.length);
+      IF (not odd (stat)) OR (stat = SS$_NOTRAN) THEN protocol_name := 'IN%';
+      fnam.length := 0;
+      IF NOT os_open_file (outbound, fnam, exclusive_read) THEN
+        mm_abort_program (os_output_file^,
+          'Can''t open outbound file                ', 24, false);
+      END; (* init *)
+     
+  PROCEDURE return_bad_messages (var bad_address : vstring);
+
+  LABEL
+    100;
+
+  VAR
+    line, errorsto : vstring;
+    bigline : bigvstring; result : rp_bufstruct;
+    header : he_header;
+    i : integer;
+
+    PROCEDURE try_something (rp_error : integer; routine : string);
+
+    BEGIN (* try_something *)
+      IF rp_isbad (rp_error) THEN BEGIN
+        warn_master ('Routine ' + routine + ' failed while returning message.');
+        mm_wkill; goto 100;
+        END; (* if *)
+      end; (* try_something *)
+
+  BEGIN (* return_bad_messages *)
+    he_init_header (header);
+    try_something (mm_sbinit, 'mm_sbinit');
+    initstring (line, 'postmaster@                             ', 11);
+    catvstring (line, mm_local_channel^.official_hostname);
+    try_something (mm_winit (bull_chan_text, line), 'mm_winit');
+    try_something (qu_rbtxt, 'qu_rbtxt');
+    try_something (he_read_header (header, qu_rtxt), 'he_read_header');
+    errorsto.length := 0;
+    IF header[he_errors_to] <> NIL THEN WITH header[he_errors_to]^ DO
+      IF ltext.length <= ALFA_SIZE THEN BEGIN
+        errorsto.length := ltext.length;
+        FOR i := 1 TO errorsto.length DO errorsto.body[i] := ltext.body[i];
+        END; (* if *)
+    IF errorsto.length > 0 THEN BEGIN
+      try_something (mm_wadr (mm_local_channel^.official_hostname, errorsto),
+                              'mm_wadr');
+      try_something (mm_rrply (result), 'mm_rrply');
+      END
+    ELSE result.rp_val := RP_NO;
+    IF rp_isbad (result.rp_val) THEN BEGIN
+      copyvstring (errorsto, fromaddr);
+      try_something (mm_wadr (mm_local_channel^.official_hostname,
+                              fromaddr), 'mm_wadr');
+      try_something (mm_rrply (result), 'mm_rrply');
+      END; (* if *)
+    IF bull_chan^.sendpost or rp_isbad (result.rp_val) THEN BEGIN
+      initstring (line,
+                  'postmaster                              ', 10);
+      try_something (mm_wadr (bull_chan^.official_hostname, line), 'mm_wadr');
+      try_something (mm_rrply (result), 'mm_rrply');
+      try_something (result.rp_val, 'mm_rrply structure return');
+      END; (* if *)
+    try_something (mm_waend, 'mm_waend');
+    initstring (line, 'From: PMDF Mail Server <Postmaster@     ', 35);
+    catvstring (line, mm_local_channel^.official_hostname);
+    catchar (line, '>');
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    initstring (line, 'To:                                     ', 4);
+    catvstring (line, errorsto);
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    initstring (line, 'Subject: Undeliverable bulletin         ', 31);
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    initstring (line, 'Date:                                   ', 6);
+    os_catdatetime (line);
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    line.length := 1; line.body[1] := chr (chr_lf);
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    initstring (line, 'The message could not be delivered to:  ', 38);
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    line.length := 1; line.body[1] := chr (chr_lf);
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    initstring (line, 'Addressee:                              ', 11);
+    catvstring (line, bad_address);
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    initstring (line, 'Reason: No such bulletin folder.        ', 32);
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    line.length := 1; line.body[1] := chr (chr_lf);
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    initstring (line, '----------------------------------------', 40);
+    catchar (line, chr (chr_lf));
+    catchar (line, chr (chr_lf));
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    try_something (he_write_header (header, mm_bigwtxt), 'he_write_header');
+    line.length := 1; line.body[1] := chr (chr_lf);
+    try_something (mm_wtxt (line), 'mm_wtxt');
+    WHILE rp_isgood (qu_rtxt (bigline)) DO
+      try_something (mm_bigwtxt (bigline), 'mm_wtxt');
+    try_something (mm_wtend, 'mm_wtend');
+    try_something (mm_rrply (result), 'mm_rrply');
+    try_something (result.rp_val, 'mm_rrply structure return');
+  100:
+    END; (* return_bad_messages *)
+
+  (* submit messages to BULLETIN *)
+     
+  PROCEDURE dosubmit;
+     
+    VAR toaddr, tombox, name : vstring;
+        retval : rp_replyval;
+        line : bigvstring;
+        ier, done : boolean;
+        i : integer;
+        chan_dummy : mm_channel_ptr;
+     
+    BEGIN (* dosubmit *)
+      WHILE NOT eof (outbound) DO BEGIN
+        readvstring (outbound, filename, 0);
+        IF rp_isgood (qu_rinit (filename, fromaddr)) THEN BEGIN
+          done := false;
+          IF rp_isgood (qu_radr (toaddr)) THEN BEGIN
+            REPEAT
+              retval := qu_radr (name);
+              UNTIL rp_isbad (retval);
+            chan_dummy := mm_parse_address (toaddr, name, tombox,
+                                            TRUE, FALSE, 0, 0);
+            FOR i := 1 TO tombox.length DO
+              tombox.body[i] := upper_case (tombox.body[i]);
+            INIT_MESSAGE_ADD (substr (tombox.body, 1, tombox.length),
+                              protocol_name, ' ', ier);
+            IF ier THEN BEGIN
+              WHILE rp_isgood (qu_rtxt (line)) DO BEGIN
+                IF line.length > 0 THEN line.length := pred (line.length);
+                WRITE_MESSAGE_LINE (substr (line.body, 1, line.length));
+                END; (* while *)
+              FINISH_MESSAGE_ADD;
+              done := true;
+              END
+            ELSE BEGIN
+	      warn_master ('Error opening folder ' +
+                           substr (tombox.body, 1, tombox.length));
+	      return_bad_messages (tombox);
+              done := true;
+              END;
+            END
+          ELSE warn_master ('Can''t read To: address in file ' +
+                            substr (filename.body, 1, filename.length));
+          IF done THEN qu_rend ELSE qu_rkill (true);
+          END
+        ELSE warn_master ('Can''t open queue file ' +
+                          substr (filename.body, 1, filename.length));
+        END; (* while *)
+      END; (* dosubmit *)
+     
+  BEGIN (* bulletin_master *)
+    init;
+    dosubmit;
+    mm_end (true);
+    qu_end;
+    END. (* bulletin_master *)
+$eod 
+$copy/log sys$input MASTER.COM
+$deck
+$ ! MASTER.COM - Initiate delivery of messages queued on a channel
+$ !
+$ ! Modification history and parameter definitions are at the end of this file.
+$ !
+$ set noon
+$ !
+$ ! Clean up and set up channel name, if on hold just exit
+$ !
+$ channel_name = f$edit(p1, "COLLAPSE,LOWERCASE")
+$ hold_list = "," + f$edit(f$logical("PMDF_HOLD"), "COLLAPSE,LOWERCASE") + ","
+$ if f$locate("," + channel_name + ",", hold_list) .lt. -
+     f$length(hold_list) then exit
+$ define/process pmdf_channel "''channel_name'"
+$ !
+$ ! Save state information, set up environment properly
+$ !
+$ save_directory = f$environment("DEFAULT")
+$ set default pmdf_root:[queue]
+$ save_protection = f$environment("PROTECTION")
+$ set protection=(s:rwed,o:rwed,g,w)/default
+$ save_privileges = f$setprv("NOSHARE")
+$ !
+$ if f$logical("PMDF_DEBUG") .eqs. "" then on control_y then goto out
+$ !
+$ ! Create listing of messages queued on this channel.
+$ !
+$ if p3 .eqs. "" then p3 = "1-JAN-1970"
+$ dirlst_file = "pmdf_root:[log]" + channel_name + "_master_dirlst_" + -
+  F$GETJPI ("", "PID") + ".tmp"
+$ define/process outbound 'dirlst_file'
+$ directory/noheader/notrailer/column=1/since="''p3'"/output='dirlst_file' -
+  pmdf_root:[queue]'channel_name'_*.%%;*
+$ !
+$ ! Determine whether or not connection should really be made
+$ !
+$ if p2 .nes. "POLL" .and. -
+     f$file_attributes(dirlst_file, "ALQ") .eq. 0 then goto out1
+$ !
+$ ! Handle various channels specially
+$ !
+$ if channel_name .eqs. "l" then goto local_channel
+$ if channel_name .eqs. "d" then goto DECnet_compatibility_channel
+$ if channel_name .eqs. "directory" then goto dir_channel
+$ if f$extract(0,5,channel_name) .eqs. "anje_"  then goto BITNET_channel
+$ if f$extract(0,4,channel_name) .eqs. "bit_"   then goto BITNET_channel
+$ if f$extract(0,5,channel_name) .eqs. "bull_"  then goto BULLETIN_channel
+$ if f$extract(0,3,channel_name) .eqs. "cn_"    then goto CN_channel
+$ if f$extract(0,5,channel_name) .eqs. "ctcp_"  then goto CTCP_channel
+$ if f$extract(0,3,channel_name) .eqs. "dn_"    then goto DECnet_channel
+$ if f$extract(0,6,channel_name) .eqs. "dsmtp_" then goto DSMTP_channel
+$ if f$extract(0,5,channel_name) .eqs. "etcp_"  then goto ETCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "ftcp_"  then goto FTCP_channel
+$ if f$extract(0,4,channel_name) .eqs. "ker_"   then goto KER_channel
+$ if f$extract(0,5,channel_name) .eqs. "mail_"  then goto MAIL_channel
+$ if f$extract(0,5,channel_name) .eqs. "mtcp_"  then goto MTCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "px25_"  then goto PX25_channel
+$ if f$extract(0,4,channel_name) .eqs. "tcp_"   then goto TCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "test_"  then goto TEST_channel
+$ if f$extract(0,5,channel_name) .eqs. "uucp_"  then goto UUCP_channel
+$ if f$extract(0,5,channel_name) .eqs. "wtcp_"  then goto WTCP_channel
+$ if f$extract(0,6,channel_name) .eqs. "xsmtp_" then goto XSMTP_channel
+$ !
+$ ! This must be a PhoneNet channel (the default); set up and use MASTER
+$ !  Read the list of valid connection types for each channel.
+$ !
+$ cnt = f$integer("0")
+$ open/read/error=regular_master pmdf_data pmdf_root:[table]phone_list.dat
+$       list_loop:
+$               read/end=eof_list pmdf_data line
+$ !  Ignore comment lines.
+$               if (f$extract (0, 1, line) .eqs. "!") then -
+                        goto list_loop
+$               line = f$edit (line, "COMPRESS,LOWERCASE")
+$ !  Get the channel name from the line read.
+$               chan = f$extract (0, f$locate(" ", line), line)
+$               if (chan .nes. channel_name) then -
+$                       goto list_loop
+$ !  Get the connection name
+$               name = f$edit(f$extract(f$locate(" ",line),255,line),"COLLAPSE")
+$ !  If none, then ignore the line
+$               if name .eqs. "" then -
+                        goto list_loop
+$ !  Found at least one to try.
+$               cnt = cnt + 1
+$               @pmdf_root:[exe]all_master.com 'name'
+$               define PMDF_DEVICE TT
+$ !
+$ ! Define other logical names
+$ !
+$ define/user script             pmdf_root:[table.'channel_name']'name'_script.
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ !
+$ !   This check attempts to verify that we are in fact the owner process of
+$ !   the device, TT.  If the device is sharable, then we ignore the
+$ !   owner.
+$ !
+$ if (f$getdvi("TT","pid") .nes. f$getjpi(0,"pid")) .and. -
+     (f$getdvi("TT","shr") .eqs. "FALSE") then -
+        goto list_loop
+$ !
+$ !  Run master to deliver the mail
+$ !
+$ run pmdf_root:[exe]master
+$ exit_stat = $status
+$ !
+$ ! Activate optional cleanup script to reset terminal/modem
+$ !
+$ if f$search("pmdf_root:[exe]''name'_cleanup.com") .nes. "" then -
+     @pmdf_root:[exe]'name'_cleanup.com 'exit_stat'
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ !
+$ !  If master does not exit normally, then try a different connection.
+$ !
+$ if exit_stat .ne. 1 then goto list_loop
+$ eof_list:
+$ close pmdf_data
+$ !
+$ !  If we found at least one connection type for this channel, then skip
+$ !  the attempt to use the conventional mechanism.
+$ !
+$ if cnt .gt. 0 then goto out_phonenet
+$ !
+$ regular_master:
+$ @pmdf_root:[exe]'channel_name'_master.com
+$ define PMDF_DEVICE TT
+$ !
+$ !  Define logical names
+$ !
+$ define/user script             pmdf_root:[table]'channel_name'_script.
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ !
+$ run pmdf_root:[exe]master
+$ exit_stat = $status
+$ !
+$ !  Activate optional cleanup script to reset terminal/modem
+$ !
+$ if f$search("''channel_name'_cleanup.com") .nes. "" then -
+     @pmdf_root:[exe]'channel_name'_cleanup.com 'exit_stat'
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ !
+$ out_phonenet:
+$ if P4 .eqs. "POST" then wait 00:00:30
+$ goto out1
+$ !
+$ ! Directory channel
+$ !
+$ dir_channel:
+$ !
+$ run pmdf_root:[exe]dir_master
+$ goto out1
+$ !
+$ ! This is a DECnet channel; set up and use DN_MASTER
+$ !
+$ DECnet_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ node_name = f$edit(channel_name - "dn_", "UPCASE")
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]di_'channel_name'_master.trn
+$ define/user ph_logfile         pmdf_root:[log]ph_'channel_name'_master.log
+$ define/user di_errfile         pmdf_root:[log]di_'channel_name'_master.log
+$ define/user pmdf_node          "''node_name'::""PMDF="""
+$ !
+$ run pmdf_root:[exe]dn_master
+$ goto out1
+$ !
+$ ! This is a BITNET channel; use BN_MASTER
+$ !
+$ BITNET_channel:
+$ !
+$ if channel_name .eqs. "bit_gateway" then goto BITNET_gateway
+$ run pmdf_root:[exe]bn_master
+$ goto out1
+$ !
+$ ! This is the BITNET gateway channel; use BN_GATEWAY
+$ !
+$ BITNET_gateway:
+$ !
+$ run pmdf_root:[exe]bn_gateway
+$ goto out1
+$ !
+$ ! This is a BULLETIN channel; use BULLETIN_MASTER
+$ !
+$ BULLETIN_channel:
+$ !
+$ run pmdf_root:[exe]bulletin_master
+$ goto out1
+$ !
+$ ! This is a Tektronix TCP channel; use TCP_MASTER
+$ !
+$ TCP_channel:
+$ !
+$ run pmdf_root:[exe]tcp_master
+$ goto out1
+$ !
+$ ! This is a CMU/Tektronix TCP channel; use CTCP_MASTER
+$ !
+$ CTCP_channel:
+$ !
+$ run pmdf_root:[exe]ctcp_master
+$ goto out1
+$ !
+$ ! This is a Wollongong TCP channel; use WTCP_MASTER
+$ !
+$ WTCP_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ run pmdf_root:[exe]wtcp_master
+$ goto out1
+$ !
+$ ! This is a MultiNet TCP channel; use MTCP_MASTER
+$ !
+$ MTCP_channel:
+$ !
+$ run pmdf_root:[exe]mtcp_master
+$ goto out1
+$ !
+$ ! This is a Excelan TCP channel; use ETCP_MASTER
+$ !
+$ ETCP_channel:
+$ !
+$ run pmdf_root:[exe]etcp_master
+$ goto out1
+$ !
+$ ! This is an NRC Fusion TCP channel; use FTCP_MASTER
+$ !
+$ FTCP_channel:
+$ !
+$ run pmdf_root:[exe]ftcp_master
+$ goto out1
+$ !
+$ CN_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ define/user script             pmdf_root:[table]'channel_name'_script.
+$ ! following may vary: should point to cnio's group
+$ define/table=lnm$process_directory lnm$temporary_mailbox lnm$group_000277
+$ !
+$ run/nodeb'p5' pmdf_root:[exe]cn_smtp_master
+$ goto out1
+$ !
+$ KER_channel:
+$ !
+$ ! kermit protocol is slave only. If we get here there has been a mistake.
+$ ! however we will just exit and no harm done.
+$ goto out1
+$ !
+$ ! This is a PhoneNet X25 channel; set up and use PX25_MASTER
+$ !
+$ PX25_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ define/user ph_current_message pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user option_file        pmdf_root:[table]'channel_name'_option.
+$ define/user di_transcript      pmdf_root:[log]'channel_name'_di_master.trn
+$ define/user ph_logfile         pmdf_root:[log]'channel_name'_ph_master.log
+$ define/user di_errfile         pmdf_root:[log]'channel_name'_di_master.log
+$ !
+$ run pmdf_root:[exe]PX25_master
+$ goto out1
+$ !
+$ ! This is a DEC/Shell channel; set up and use UUCP_MASTER
+$ !
+$ UUCP_channel:
+$ !
+$ ! Define other logical names
+$ !
+$ uucp_to_host = channel_name - "uucp_"
+$ define/user uucp_to_host       "''uucp_to_host'"
+$ define/user uucp_current_message -
+  pmdf_root:[log]'channel_name'_master_curmsg.tmp
+$ define/user uucp_logfile       pmdf_root:[log]'channel_name'_master.logfile
+$ !
+$ run pmdf_root:[exe]UUCP_master
+$ uupoll = "$shell$:[usr.lib.uucp]uupoll"
+$ uupoll 'uucp_to_host'
+$ goto out1
+$ !
+$ ! This is a X.25 SMTP channel; set up and use XSMTP_MASTER
+$ !
+$ XSMTP_channel:
+$ !
+$ run pmdf_root:[exe]xsmtp_master
+$ goto out1
+$ !
+$ ! This is a DECNET SMTP channel; set up and use DSMTP_MASTER
+$ !
+$ DSMTP_channel:
+$ !
+$ run pmdf_root:[exe]dsmtp_master
+$ goto out1
+$ !
+$ ! Handle delivery on the local channel, MAIL_ channels, and
+$ ! the DECnet compatibility channel
+$ !
+$ MAIL_channel:
+$ local_channel:
+$ DECnet_compatibility_channel:
+$ open/read queue_file 'dirlst_file'
+$ local_loop:
+$   read/end=exit_local_loop/error=exit_local_loop  queue_file file_to_process
+$   priv_list = f$setprv("SYSPRV, DETACH")
+$   mail/protocol=pmdf_mailshr 'file_to_process'
+$   priv_list = f$setprv(priv_list)
+$ goto local_loop
+$ !
+$ exit_local_loop:
+$ close queue_file
+$ goto out1
+$ !
+$ ! This is a SMTP test channel, use TEST_SMTP_MASTER
+$ !
+$ TEST_channel:
+$ !
+$ ! Typically some form of redirection is needed here...
+$ deassign sys$input
+$ run pmdf_root:[exe]test_smtp_master
+$ goto out1
+$ !
+$ out1:
+$ delete 'dirlst_file';*
+$ !
+$ ! Common exit point - clean up things first
+$ !
+$ out:
+$ if f$logical("OUTBOUND") .nes. "" then deassign/process outbound
+$ if f$logical("PMDF_CHANNEL") .nes. "" then deassign/process pmdf_channel
+$ if f$logical("PMDF_DATA") .nes. "" then close pmdf_data
+$ if f$logical("PMDF_DEVICE") .eqs. "" then goto restore
+$ deallocate TT
+$ deassign TT
+$ deassign PMDF_DEVICE
+$ restore:
+$ !
+$ ! Restore saved stuff
+$ !
+$ set protection=('save_protection')/default
+$ set default 'save_directory'
+$ set process/priv=('save_privileges')
+$ !
+$ exit
+$ !
+$ ! Modification history:
+$ !
+$ ! This version by Ned Freed, 20-Jul-1986
+$ !
+$ ! Modified by Gregg Wonderly to allow multiple connections for each channel
+$ !   10-Oct-1986.
+$ ! Some additions by Ned Freed 30-Oct-86.
+$ ! Added CMU/Tektronix TCP channel (CTCP) /Kevin Carosso 6-Mar-1987
+$ ! Added Multinet TCP channel (MTCP) /Ned Freed 10-Mar-1987
+$ ! Added directory save/restore /Ned Freed 1-Jun-1987
+$ ! Added Excelan TCP channel (ETCP) /Ned Freed 9-Jul-1987
+$ ! Added MAIL, CNIO, KERMIT channel /Bob Smart 4-Jul-1987
+$ ! Added Warwick Jackson's PhoneNet X25 support /Ned Freed 5-Sep-87
+$ ! Added X25 SMTP channel SX25_ /Goeran Bengtsson, Mats Sundvall 24-Jul-87
+$ ! Added NRC Fusion TCP channel (FTCP) /Kevin Carosso 12-Jan-1988
+$ ! Added a variant of Randy McGee's code to put a list of channels on hold
+$ !   /Ned Freed 9-Feb-1988
+$ ! Made this procedure save and restore a little more state information
+$ !   than it used to, including default protection and privileges. Also
+$ !   moved a bunch of the logical name assignments around to eliminate
+$ !   redundant code all over the place. /Ned Freed 10-Feb-1988
+$ ! Modified to allow P3 date/time paramter. /Ned Freed 23-Feb-1988
+$ ! Added support for Dennis Boylan's UUCP channel. /Ned Freed 28-Mar-1988
+$ ! Added Robert Smart's directory channel. /Ned Freed 21-Apr-1988
+$ ! Added support for Warwick Jackson's SMTP over X.25 and SMTP over
+$ !   DECnet channels. /Ned Freed 26-May-1988
+$ ! Added P4 and P5 parameters. /Ned Freed 10-Jun-1988
+$ ! Added code to call the TEST_SMTP_MASTER for testing. /Ned Freed 1-Jul-1988
+$ ! Added preliminary support for ANJE. /Ned Freed 7-Jul-1988
+$ ! Removed extra dispatch for WTCP_ channel. /Ned Freed 3-Sep-1988
+$ ! Added dispatch for BULL_ channel. /Ned Freed 28-Nov-1988
+$ ! Cleaned up error recovered and emergency exit -- close PHONE_LIST.DAT
+$ !   file when aborting. /Ned Freed 13-Dec-1988
+$ ! Additional error recovery cleanup -- use PMDF_DEVICE instead of TT to
+$ !   allow deallocation on an abort. /Ned Freed 14-Dec-1988
+$ !
+$ ! Parameters:
+$ !
+$ !   P1 - Name of the channel whose messages are to be delivered.
+$ !   P2 - Activity type. If P2 .eqs. "POLL", establish the connection
+$ !        unconditionally, otherwise only establish the connection if
+$ !        messages are waiting in the queue.
+$ !   P3 - Earliest possible date/time for message(s). Messages older than
+$ !        this time are not processed.
+$ !   P4 - Environment. P4 .eqs. "POST" if MASTER is being called from the
+$ !        POST.COM procedure or some other procedure that invokes MASTER
+$ !        more than once. This parameter is used to insert delays before
+$ !        returning if hardware needs time to reset.
+$ !   P5 - Parameter reserved for channel-specific uses.
+$eod 
+$copy/log sys$input PMDF.TXT
+$deck
+This describes the procedure necessary to use BULLETIN with PMDF.  You must
+be using at least PMDF V3.1.  If using V3.2 you will instead have to use
+BULLETIN_MASTER.PAS_V32.  V3.2 does come with it's own BULLETIN_MASTER.PAS, but
+there is a small bug in it.  If you are using V4.0 or later, use the command
+procedure PMDF_ROOT:[SRC]PMDF_BULLETIN.COM and ignore the files that are 
+distributed with BULLETIN.
+
+BULLETIN_MASTER.PAS and MASTER.COM are the files you need to run a BULLETIN
+channel.  Put BULLETIN_MASTER.PAS in a subdirectory of PMDF_ROOT:[SRC] (I use
+the directory PMDF_ROOT:[SRC.BULLETIN]). Compile it there and then link it as
+follows.  This might result in undefined reference errors.  You can ignore them,
+as these are routines that are used for connecting to USENET NEWS, and are not
+used by the BULLETIN_MASTER executable.
+
+For V3.1:
+
+    LINK /EXE=PMDF_ROOT:[EXE]BULLETIN_MASTER -
+    BULLETIN_MASTER,[EXE]PMDFLIB/LIB,BULL_SOURCE:BULL/LIB, -
+    PMDF_ROOT:[EXE]VAXC/OPT
+
+For V3.2:
+
+    LINK /EXE=PMDF_ROOT:[EXE]BULLETIN_MASTER -
+    BULL_DIR:BULLETIN_MASTER,PMDF_ROOT:[EXE]PMDFSHR_LINK.OPT/OPT, -
+    [EXE]IDENT.OPT/OPT,BULL_SOURCE:BULL.OLB/LIB,PMDF_ROOT:[EXE]VAXC/OPT
+
+If you need to, put the new MASTER.COM in PMDF_ROOT:[EXE]. NOTE: Check your
+MASTER.COM, as the latest version of PMDF contains the code necessary to check
+for bulletin mail.  However, it will not necessary have the latest copy of
+BULLETIN_MASTER.PAS. 
+
+You then need a channel definition like the following in your configuration
+file PMDF.CNF:
+
+    bull_local single logging
+    BULLETIN-DAEMON
+
+And a rewrite rule of the form:
+
+    BULLETIN                          $U%BULLETIN@BULLETIN-DAEMON
+
+Then you put an alias in your ALIASES. file for each mailing list you want to
+process this way. I have the following:
+
+    info-vax: info-vax@bulletin
+    tex-hax: tex-hax@bulletin
+    xmailer-list: xmailer@bulletin
+    mail-l: mail-l@bulletin
+    jnet-l: jnet-l@bulletin
+    policy-l: policy-l@bulletin
+    future-l: future-l@bulletin
+    mon-l: mon-l@bulletin
+    ug-l: ug-l@bulletin
+
+Then mail sent to info-vax@localhost will be routed to a folder called
+info-vax. In general, an alias of the form
+
+    a : b@bulletin
+
+will route mail sent to a@localhost to folder b in BULLETIN.
+
+NOTE: If you have BBOARD set for a folder that you convert to be delivered
+directly to PMDF, remember to do a SET NOBBOARD for that folders (unless
+using the LISTSERV option.  See HELP SET BBOARD LISTSERV for more info).  After
+doing so, restart BULLCP using BULLETIN/START.
+$eod 
diff --git a/decus/vmslt98a/bulletin/restart.com b/decus/vmslt98a/bulletin/restart.com
new file mode 100755
index 0000000000000000000000000000000000000000..71f7023963e7b796667f566c7ebdc319bb46a233
--- /dev/null
+++ b/decus/vmslt98a/bulletin/restart.com
@@ -0,0 +1,6 @@
+$ SET PROCESS/PRIVILEGE=ALL
+$ MCR SYSMAN
+SET ENV/CL
+SET PROF/PRIV=ALL
+DO DEASSIGN BULL_DISABLE/SYSTEM
+$ BULL/START
diff --git a/decus/vmslt98a/bulletin/setuser.mar b/decus/vmslt98a/bulletin/setuser.mar
new file mode 100755
index 0000000000000000000000000000000000000000..489f36fa37a2928fdfa6599c08a07c07b87e4c00
--- /dev/null
+++ b/decus/vmslt98a/bulletin/setuser.mar
@@ -0,0 +1,125 @@
+	.Title	SETUSER
+;
+;	Program Setuser
+;
+;	This program will change the username and UIC of the running process
+;
+;	To assemble:	$ MACRO SETUSER
+;			$ LINK SETUSER,SYS$SYSTEM:SYS.STB/SELECT
+;
+	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
+	$PCBDEF				;define PCB offsets
+	$JIBDEF				;define JIB offsets
+	$UAFDEF				;define user authorization file offsets
+INFAB:	$FAB	FAC=GET -		;only gets on input file
+		FNM=<SYSUAF> -		;SYSUAF may be defined as logical name
+		DNM=<SYS$SYSTEM:.DAT> -	;These are default directory & suffix
+		SHR=<PUT,GET,DEL,UPD>	;allow full sharing
+INRAB:	$RAB	FAB=INFAB -		;FAB for this RAB
+		KBF=COMMLD+8 -		;key value is typed in by user
+		KRF=0 -			;primary key
+		KSZ=12 -		;username is 12 bytes long
+		RAC=KEY -		;key access on this file
+		ROP=NLK -		;don't lock read records
+		UBF=BUFFER -		;address of buffer for I/O
+		USZ=2048		;size of buffer
+BUFFER:	.BLKB	2048			;buffer for data
+COMMLD:	.ASCID	/            /		;space for typed in username
+PROMPTD:.ASCID	/Username: /		;prompt string
+COMMLDS:.WORD	0			;space for number of bytes typed in
+FAODESC:.LONG	80
+	.LONG	FAOBUF
+FAOBUF:	.BLKB	80
+FAOLEN:	.BLKW	1
+	.BLKW	1
+FORSTR:	.ASCID	/PID:!XL from:[!OW,!OW] !AD to:[!OW,!OW] !AD/
+TT:	.ASCID	/SYS$OUTPUT/
+CHANTT:	.WORD	0			;space for terminal channel number
+IOSB:	.QUAD	0
+OLDUSER:.BLKB	12			;space for old username
+OLDUIC:	.BLKL	1			;space for old uic
+ERRORB:	JMP	ERROR			;for branch out of range
+
+JPIUSER:	.BLKB	12
+JPIUSER_LEN:	.BLKL	1
+
+	$DEFINI IT			;DEFINE ITEM LIST FOR GETJPI
+$DEF	ITL	.BLKW	1		;LENGTH OF OUTPUT BUFFER
+$DEF	ITM	.BLKW	1		;ITEM CODE (PROCESS NAME)
+$DEF	ITA	.BLKL	1		;ADDR OF OUTPUT BUFFER
+$DEF	ITAL	.BLKL	1		;ADDR OF WORD TO RECIEVE BYTES USED
+$DEF	ITEND	.BLKL	1		;ZERO LONG WORD TO END LIST
+$DEF	ITSIZE				;SIZE NEEDED FOR IT BLOCK
+	$DEFEND IT
+
+	.ENTRY	START,^M<>		;start of program
+	PUSHAW	COMMLDS			;address of word to get read byte count
+	PUSHAL	PROMPTD			;address of prompt string descriptor
+	PUSHAL	COMMLD			;address of descriptor to get command
+	CALLS	#3,G^LIB$GET_FOREIGN	;use run time library to get command
+	BLBC	R0,ERRORB		;low bit clear error
+	$OPEN	FAB=INFAB		;open file
+	BLBC	R0,ERRORB		;low bit clear error
+	$CONNECT RAB=INRAB		;connect file
+	BLBC	R0,ERRORB		;low bit clear error
+	$GET	RAB=INRAB		;read a record
+	CMPL	R0,#RMS$_RNF		;record not found?
+	BEQL	errorb			;that's all folks
+	CMPL	R0,#RMS$_NORMAL		;ok?
+	BNEQ	ERRORB			;no so quit
+
+	SUBL	#ITSIZE,SP		;GET SPACE FOR ITEM LIST
+	MOVL	SP,R2			;POINT TO IT
+	MOVW	#12,ITL(R2)		;SET UP ITEM LIST
+	MOVW	#JPI$_USERNAME,ITM(R2)
+	MOVAB	JPIUSER,ITA(R2)
+	MOVAW	JPIUSER_LEN,ITAL(R2)
+	CLRL	ITEND(R2)
+	$GETJPI_S	ITMLST=(R2)	;GET PROCESS NAME
+	ADDL	#ITSIZE,SP		;RESTORE STACK POINTER
+
+	MOVL	INRAB+RAB$L_RBF,R7	;put address of read record in R7
+	MOVL	UAF$L_UIC(R7),R8	;R8 has UIC we want
+	$CMKRNL_S TWEAK			;change mode to kernel to tweak UIC
+					;and username
+	BLBC	R0,ERROR		;low bit clear error
+	ADDL3	#UAF$S_USERNAME,R7,R8
+	ADDL3	#UAF$T_USERNAME,R7,R9
+	$FAO_S	CTRSTR=FORSTR,-		;format string
+		OUTBUF=FAODESC,-	;char descript for formatted output
+		OUTLEN=FAOLEN,-		;long word to hold length of output
+		P1=R9,-			;PID
+		P2=OLDUIC+2,-		;old UIC, group number
+		P3=OLDUIC,-		;old UIC, member number
+		P4=#12,-		;usernames are 12 bytes
+		P5=#OLDUSER,-		;address of old username
+		P6=UAF$L_UIC+2(R7),-	;UIC, group number
+		P7=UAF$L_UIC(R7),-	;UIC, member number
+		P8=R8,-			;usernames are 12 bytes
+		P9=R9			;address of username
+	BLBC	R0,ERROR		;low bit clear error
+	MOVL	FAOLEN,FAODESC
+	PUSHAL	FAODESC			;address of descriptor to get command
+	CALLS	#1,G^LIB$PUT_OUTPUT	;use run time library to get command
+	BLBC	R0,ERROR		;low bit clear error
+EXIT:
+	$CLOSE	FAB=INFAB -		;close file
+		ERR=ERROR
+ERROR:	$EXIT_S	R0			;exit with error if any
+	.ENTRY	TWEAK,^M<>		;beginning of kernel mode code
+	MOVL	@#CTL$GL_PCB,R11	;put address of our PCB in R11
+	MOVL	PCB$L_PID(R11),R9	;save PID
+	MOVL	PCB$L_UIC(R11),OLDUIC	;save old UIC
+	MOVL	R8,PCB$L_UIC(R11)	;change our UIC
+	MOVL	PCB$L_JIB(R11),R10	;put address of Job Info Block in R10
+					;MOVC blats R0-R5
+	MOVC3	#12,JIB$T_USERNAME(R10),OLDUSER ;save old username
+	CMPC3	JPIUSER_LEN,JPIUSER,OLDUSER
+	BEQL	GOOD
+	CLRL	R0
+	RET	
+GOOD:	MOVC3	#12,UAF$T_USERNAME(R7),JIB$T_USERNAME(R10) ;change username JIB
+	MOVC3	#12,UAF$T_USERNAME(R7),CTL$T_USERNAME ;change username in P1
+EEXIT:	MOVL	#SS$_NORMAL,R0		;set normal exit status
+	RET				;end of exec mode code
+	.END	START			;end of program
diff --git a/decus/vmslt98a/bulletin/update.fil b/decus/vmslt98a/bulletin/update.fil
new file mode 100755
index 0000000000000000000000000000000000000000..06f3135cc7f708d26c427ed9b388e5c9706af4cc
--- /dev/null
+++ b/decus/vmslt98a/bulletin/update.fil
@@ -0,0 +1,11 @@
+$ if p1 .nes. "" then FS 'P1'
+$ COPY 'FM' [.SEND]/LOG
+$ COPY 'FM' CMODA::IR:[BULLETIN]
+$ TAB2SP 'FM' 
+$ RENAME 'FM' [-.NET]
+$ PUR [.SEND]'FM'
+$ PUR [-.NET]'FM'
+$ IF FM .EQS. "CHMAIL.MAI" THEN P3 = "AAAREADME."
+$ IF P2 .EQS. "" THEN COPY 'FM' [ANONYMOUS.BULLETIN]'P3'
+$ IF P3 .EQS. "" THEN PUR [ANONYMOUS.BULLETIN]'FM'
+$ IF P3 .NES. "" THEN PUR [ANONYMOUS.BULLETIN]'p3'
diff --git a/decus/vmslt98a/bulletin/upgrade.com b/decus/vmslt98a/bulletin/upgrade.com
new file mode 100755
index 0000000000000000000000000000000000000000..b91fa7ce7837d054cd932fc7901c1c782153454b
--- /dev/null
+++ b/decus/vmslt98a/bulletin/upgrade.com
@@ -0,0 +1,53 @@
+$!
+$!  Normally, new versions of BULLETIN don't require any special
+$!  installation except to link and install the new executable (and
+$!  possibly relink PMDF or MX interfaces if any changes affect them).
+$!  However, when there is a change to the data file format, you should run
+$!  the following procedure.         
+$!
+$!  This is a sample upgrade procedure.  You will have to modify references
+$!  to the directory where the new executables are stored, which are marked
+$!  with ***. You will also have to change the references to the procedures
+$!  that link either PMDF or MX.  These procedures usually replace the old
+$!  executable, but that should not be done until BULLETIN has been disabled
+$!  (by defining the logical name BULL_DISABLE).  If you run this procedure
+$!  with a parameter (i.e. @UPGRADE LINK), it will call those linking
+$!  procedures. Alternatively, you could define BULL_DISABLE and run those
+$!  procedures manually.  Or, you could change them so they don't replace the
+$!  old procedures and run them manually, and simply have this procedure
+$!  replace them.  Whatever you find more convenient.
+$!  
+$!  This procedure should be run on all stand alone nodes or boot nodes of
+$!  clusters on which bulletin is installed. After running upgrade.com, run
+$!  restart.com to restart bulletin.  If you don't make use of remote
+$!  folders, you can run restart.com immediately after upgrade.com rather
+$!  than waiting to install the new version on all nodes.  Otherwise, you
+$!  should try to run this procedure simultaneously on all clusters and then
+$!  wait until it finishes on all nodes before running restart.com. 
+$!  Otherwise, remote folder access attempts will fail.                 
+$!  
+$ SET PROCESS/PRIVILEGE=ALL
+$ COPY ALCVAX::USER1:[MRL.BULLETIN]BULLETIN.EXE BULL_DIR:              ! *** 
+$ COPY ALCVAX::USER1:[MRL.BULLETIN]BULL.HLB SITE$ROOT:[SYSHLP]         ! *** 
+$ PMDF = F$TRNLNM("PMDF_ROOT")
+$ MX = F$TRNLNM("MX_EXE")
+$ BULL/STOP
+$ IF PMDF .NES. "" THEN PMDF = F$SEARCH("PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE")
+$ IF PMDF .NES. "" THEN DELETE/NOCONFIRM PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE;*
+$ IF MX .NES. "" THEN MX = F$SEARCH("MX_EXE:MX_BULL.EXE")
+$ IF MX .NES. "" THEN DELETE/NOCONFIRM MX_EXE:MX_BULL.EXE;*
+$ MCR SYSMAN
+SET ENV/CL
+SET PROF/PRIV=ALL
+DO DEFINE BULL_DISABLE/SYSTEM "DISABLE"
+DO MCR INSTALL BULL_DIR:BULLETIN/REPLACE
+$ IF P1 .NES. "" .AND. PMDF .NES. "" THEN @USER1:[MRL.BULLETIN]LINK_PMDF ! ***
+$ IF P1 .NES. "" .AND. MX .NES. "" THEN @USER1:[MRL.BULLETIN]LINK_MX	 ! ***
+$ DEFINE BULL_DISABLE "ENABLE"		! Enable it just for this process.
+$ BULLETIN
+$ IF F$TRNLNM("BULL_NEWS_SERVER") .NES. "" THEN BULLETIN MISC.TEST
+$ IF PMDF .NES. "" THEN-
+   COPY ALCVAX::PMDF_ROOT:[EXE]BULLETIN_MASTER.EXE PMDF_ROOT:[EXE]	! ***
+$ IF MX .NES. "" THEN-
+   COPY ALCVAX::MX_EXE:MX_BULL.EXE MX_EXE:                 		! ***
+$ DEASSIGN BULL_DISABLE
diff --git a/decus/vmslt98a/bulletin/writemsg.txt b/decus/vmslt98a/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..2bfabfdabc8b43294194358412f5464016f9de3f
--- /dev/null
+++ b/decus/vmslt98a/bulletin/writemsg.txt
@@ -0,0 +1,36 @@
+BULLETIN contains subroutines for writing a message directly to a folder.  This
+would be useful for someone who is using the BBOARD feature, but wants to avoid
+the extra overhead of having the message sent to an account as MAIL, and then
+have BULLCP read the mail.  It is better if the network mail could be written
+directly to the folder bypassing VMS MAIL, as it reduces a lot of cpu overhead.
+
+Call INIT_MESSAGE_ADD to initiate a message addition.
+Call WRITE_MESSAGE_LINE to write individual message lines.
+Call FINISH_MESSAGE_ADD to complete a message addition.
+
+Calling formats:
+
+	CALL INIT_MESSAGE_ADD(IN_FOLDER,IN_FROM,IN_DESCRIP,IER)
+C
+C  INPUTS:
+C	IN_FOLDER  - Character string containing folder name
+C	IN_FROM	   - Character string containing name of owner of message.
+C		     If empty, the default is the owner of the process.
+C	IN_DESCRIP - Character string containing subject of message.
+C		     If empty, the message is searched for a line
+C		     which starts with "Subj:" or "Subject:".
+C  OUTPUTS:
+C	IER - Error status.  True if properly connected to folder.
+C		False if folder not found.
+C
+
+	CALL WRITE_MESSAGE_LINE(BUFFER)
+C
+C  INPUTS:
+C	BUFFER - Character string containing line to be put into message.
+C
+
+	CALL FINISH_MESSAGE_ADD
+C
+C  NOTE:  Only should be run if INIT_MESSAGE_ADD was successful.
+C
diff --git a/decus/vmslt98b/bulletin/aaareadme.1st b/decus/vmslt98b/bulletin/aaareadme.1st
new file mode 100755
index 0000000000000000000000000000000000000000..e3d297e202bd916e66b2326de901482ce4fb8859
Binary files /dev/null and b/decus/vmslt98b/bulletin/aaareadme.1st differ
diff --git a/decus/vmslt98b/bulletin/aaareadme.txt b/decus/vmslt98b/bulletin/aaareadme.txt
new file mode 100755
index 0000000000000000000000000000000000000000..d79cb80ec75dea9ca4365d3834b3199f9488fb3d
Binary files /dev/null and b/decus/vmslt98b/bulletin/aaareadme.txt differ
diff --git a/decus/vmslt98b/bulletin/allmacs.mar b/decus/vmslt98b/bulletin/allmacs.mar
new file mode 100755
index 0000000000000000000000000000000000000000..4a6072cffdf2449766b6f0edc21b8eee640b7308
Binary files /dev/null and b/decus/vmslt98b/bulletin/allmacs.mar differ
diff --git a/decus/vmslt98b/bulletin/allmacs_axp.mar b/decus/vmslt98b/bulletin/allmacs_axp.mar
new file mode 100755
index 0000000000000000000000000000000000000000..4405fa1809177e174b0a7796bc3b4581ed1ee772
Binary files /dev/null and b/decus/vmslt98b/bulletin/allmacs_axp.mar differ
diff --git a/decus/vmslt98b/bulletin/bad.for b/decus/vmslt98b/bulletin/bad.for
new file mode 100755
index 0000000000000000000000000000000000000000..4923eeaf38d5a48a86171de61d9cf12ae3175d96
Binary files /dev/null and b/decus/vmslt98b/bulletin/bad.for differ
diff --git a/decus/vmslt98b/bulletin/board_digest.com b/decus/vmslt98b/bulletin/board_digest.com
new file mode 100755
index 0000000000000000000000000000000000000000..54a23cf246cacc7ec3b49a11fbac87f5d44db9dd
Binary files /dev/null and b/decus/vmslt98b/bulletin/board_digest.com differ
diff --git a/decus/vmslt98b/bulletin/board_special.com b/decus/vmslt98b/bulletin/board_special.com
new file mode 100755
index 0000000000000000000000000000000000000000..e6ff014483565e3b6f13a05e42ba24b8178f9da3
Binary files /dev/null and b/decus/vmslt98b/bulletin/board_special.com differ
diff --git a/decus/vmslt98b/bulletin/bull_news.c b/decus/vmslt98b/bulletin/bull_news.c
new file mode 100755
index 0000000000000000000000000000000000000000..afd6a68e6ea7845a8862a2e807a5e3da3409a4e3
Binary files /dev/null and b/decus/vmslt98b/bulletin/bull_news.c differ
diff --git a/decus/vmslt98b/bulletin/bull_newsdummy.for b/decus/vmslt98b/bulletin/bull_newsdummy.for
new file mode 100755
index 0000000000000000000000000000000000000000..9bc04a28d243c2270dabf0b669b7efdceaf4079c
Binary files /dev/null and b/decus/vmslt98b/bulletin/bull_newsdummy.for differ
diff --git a/decus/vmslt98b/bulletin/bullcom.cld b/decus/vmslt98b/bulletin/bullcom.cld
new file mode 100755
index 0000000000000000000000000000000000000000..b3840a561ebdcedfc77e989962c153d1ce81e0ff
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullcom.cld differ
diff --git a/decus/vmslt98b/bulletin/bullcoms1.hlp b/decus/vmslt98b/bulletin/bullcoms1.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..eb227c8307b9317065942db036d78d0c580c625a
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullcoms1.hlp differ
diff --git a/decus/vmslt98b/bulletin/bullcoms2.hlp b/decus/vmslt98b/bulletin/bullcoms2.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..244d877eb89d9e2e381cb012da4afe625faa4492
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullcoms2.hlp differ
diff --git a/decus/vmslt98b/bulletin/bulldir.inc b/decus/vmslt98b/bulletin/bulldir.inc
new file mode 100755
index 0000000000000000000000000000000000000000..9f9d356f1ebfa80c3895d9343dbd9e4b0af165f1
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulldir.inc differ
diff --git a/decus/vmslt98b/bulletin/bullet1.com b/decus/vmslt98b/bulletin/bullet1.com
new file mode 100755
index 0000000000000000000000000000000000000000..8f59f560dac7be429dce4f708d95bee49a40b923
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullet1.com differ
diff --git a/decus/vmslt98b/bulletin/bullet2.com b/decus/vmslt98b/bulletin/bullet2.com
new file mode 100755
index 0000000000000000000000000000000000000000..c3c1bdab7f2d3ab1b3343ed852eb5ccaa9e55d36
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullet2.com differ
diff --git a/decus/vmslt98b/bulletin/bulletin.cld b/decus/vmslt98b/bulletin/bulletin.cld
new file mode 100755
index 0000000000000000000000000000000000000000..7faee4731dc00791d45b3f85429bef300f31f5ff
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin.cld differ
diff --git a/decus/vmslt98b/bulletin/bulletin.com b/decus/vmslt98b/bulletin/bulletin.com
new file mode 100755
index 0000000000000000000000000000000000000000..722453311b226491ede99efa98cb8e3b3b24cdc4
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin.com differ
diff --git a/decus/vmslt98b/bulletin/bulletin.for b/decus/vmslt98b/bulletin/bulletin.for
new file mode 100755
index 0000000000000000000000000000000000000000..0e650e000ba0e4a9b8e90399fac395d9a41dde1a
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin.hlp b/decus/vmslt98b/bulletin/bulletin.hlp
new file mode 100755
index 0000000000000000000000000000000000000000..696f7a6fcfc46f611af407a2b8b74bc205861d57
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin.hlp differ
diff --git a/decus/vmslt98b/bulletin/bulletin.lnk b/decus/vmslt98b/bulletin/bulletin.lnk
new file mode 100755
index 0000000000000000000000000000000000000000..069ea4706645239fbb905ee93e63db36dfadfeaf
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin.lnk differ
diff --git a/decus/vmslt98b/bulletin/bulletin0.for b/decus/vmslt98b/bulletin/bulletin0.for
new file mode 100755
index 0000000000000000000000000000000000000000..1a30390e72a9728c86851ae62ea41ff46f07b006
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin0.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin1.for b/decus/vmslt98b/bulletin/bulletin1.for
new file mode 100755
index 0000000000000000000000000000000000000000..a46787158d0423742e414b43ce99876818d54a9b
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin1.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin10.for b/decus/vmslt98b/bulletin/bulletin10.for
new file mode 100755
index 0000000000000000000000000000000000000000..4ba43e19077934833c90005254602f12070dc87b
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin10.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin11.for b/decus/vmslt98b/bulletin/bulletin11.for
new file mode 100755
index 0000000000000000000000000000000000000000..583ceaeb3d9be3aff421684ab8425c713dbb4f76
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin11.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin2.for b/decus/vmslt98b/bulletin/bulletin2.for
new file mode 100755
index 0000000000000000000000000000000000000000..c43c10289f1004183fbfc0091223ba19bdfbb422
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin2.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin3.for b/decus/vmslt98b/bulletin/bulletin3.for
new file mode 100755
index 0000000000000000000000000000000000000000..7e1406eaaef01af47e81612ece360f4520e232d5
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin3.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin4.for b/decus/vmslt98b/bulletin/bulletin4.for
new file mode 100755
index 0000000000000000000000000000000000000000..3eff9e3e6fa99d2d9587e50f7cef9816386f263c
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin4.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin5.for b/decus/vmslt98b/bulletin/bulletin5.for
new file mode 100755
index 0000000000000000000000000000000000000000..9c3ab1f03f9002d89e95651668d39386b2fc9e5f
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin5.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin6.for b/decus/vmslt98b/bulletin/bulletin6.for
new file mode 100755
index 0000000000000000000000000000000000000000..af0957b2a8be4c8b59deec01dae76cd1319f457f
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin6.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin7.for b/decus/vmslt98b/bulletin/bulletin7.for
new file mode 100755
index 0000000000000000000000000000000000000000..9793ef9d1dfd8f2c9ab33f13e41fb4a5e86dc568
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin7.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin8.for b/decus/vmslt98b/bulletin/bulletin8.for
new file mode 100755
index 0000000000000000000000000000000000000000..e8a315e7b8f86154c6cd142ddbfbcf7b22bcc305
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin8.for differ
diff --git a/decus/vmslt98b/bulletin/bulletin9.for b/decus/vmslt98b/bulletin/bulletin9.for
new file mode 100755
index 0000000000000000000000000000000000000000..1e5fc713b6a7e93935fb292d549a923d6e88705a
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulletin9.for differ
diff --git a/decus/vmslt98b/bulletin/bullfiles.inc b/decus/vmslt98b/bulletin/bullfiles.inc
new file mode 100755
index 0000000000000000000000000000000000000000..37bde435b1808ea284d5217f21fafd815bb1d52c
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullfiles.inc differ
diff --git a/decus/vmslt98b/bulletin/bullfolder.inc b/decus/vmslt98b/bulletin/bullfolder.inc
new file mode 100755
index 0000000000000000000000000000000000000000..66c3ebb63d12e56679ad279a549cdb5a8db40fe6
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullfolder.inc differ
diff --git a/decus/vmslt98b/bulletin/bullmain.cld b/decus/vmslt98b/bulletin/bullmain.cld
new file mode 100755
index 0000000000000000000000000000000000000000..1eb4f959603b8042d1546c47518b6477f2dd04e5
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullmain.cld differ
diff --git a/decus/vmslt98b/bulletin/bullnews.inc b/decus/vmslt98b/bulletin/bullnews.inc
new file mode 100755
index 0000000000000000000000000000000000000000..6600ba017c36f39574caf53bdca982f45788bb7a
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullnews.inc differ
diff --git a/decus/vmslt98b/bulletin/bullstart.com b/decus/vmslt98b/bulletin/bullstart.com
new file mode 100755
index 0000000000000000000000000000000000000000..c97417c6dbb21d98dc84ee9f3fb5da4fa555e1b6
Binary files /dev/null and b/decus/vmslt98b/bulletin/bullstart.com differ
diff --git a/decus/vmslt98b/bulletin/bulluser.inc b/decus/vmslt98b/bulletin/bulluser.inc
new file mode 100755
index 0000000000000000000000000000000000000000..89df9193041fb6e1dc9835e34380508edf39c911
Binary files /dev/null and b/decus/vmslt98b/bulletin/bulluser.inc differ
diff --git a/decus/vmslt98b/bulletin/changes.txt b/decus/vmslt98b/bulletin/changes.txt
new file mode 100755
index 0000000000000000000000000000000000000000..94b189e9548a9a17916214eb121581924aa1f5c8
Binary files /dev/null and b/decus/vmslt98b/bulletin/changes.txt differ
diff --git a/decus/vmslt98b/bulletin/cmds.mai b/decus/vmslt98b/bulletin/cmds.mai
new file mode 100755
index 0000000000000000000000000000000000000000..b747457a0e66370e0900b57943b54f7f6c1231cc
Binary files /dev/null and b/decus/vmslt98b/bulletin/cmds.mai differ
diff --git a/decus/vmslt98b/bulletin/copyright.txt b/decus/vmslt98b/bulletin/copyright.txt
new file mode 100755
index 0000000000000000000000000000000000000000..9109280949b210763ea1e18b0fe8b77cc9dea657
Binary files /dev/null and b/decus/vmslt98b/bulletin/copyright.txt differ
diff --git a/decus/vmslt98b/bulletin/create.com b/decus/vmslt98b/bulletin/create.com
new file mode 100755
index 0000000000000000000000000000000000000000..fd4baaa7c4cadad96c5a9c08dd209e761f566515
Binary files /dev/null and b/decus/vmslt98b/bulletin/create.com differ
diff --git a/decus/vmslt98b/bulletin/createco.com b/decus/vmslt98b/bulletin/createco.com
new file mode 100755
index 0000000000000000000000000000000000000000..7c142707522aa0409acbda3d51c57ca83194f352
Binary files /dev/null and b/decus/vmslt98b/bulletin/createco.com differ
diff --git a/decus/vmslt98b/bulletin/handout.txt b/decus/vmslt98b/bulletin/handout.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96973956abb615628b54ad5ce370affc258a99ff
Binary files /dev/null and b/decus/vmslt98b/bulletin/handout.txt differ
diff --git a/decus/vmslt98b/bulletin/install.com b/decus/vmslt98b/bulletin/install.com
new file mode 100755
index 0000000000000000000000000000000000000000..530e4a827a5ce3865875fa3ed27d4b02652102a9
Binary files /dev/null and b/decus/vmslt98b/bulletin/install.com differ
diff --git a/decus/vmslt98b/bulletin/instruct.com b/decus/vmslt98b/bulletin/instruct.com
new file mode 100755
index 0000000000000000000000000000000000000000..4487801de36fb7dcdcb08028e7f7338cf88a23d8
Binary files /dev/null and b/decus/vmslt98b/bulletin/instruct.com differ
diff --git a/decus/vmslt98b/bulletin/instruct.txt b/decus/vmslt98b/bulletin/instruct.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8193348028f8ab33bca2bad9236acfa8d3e9d686
Binary files /dev/null and b/decus/vmslt98b/bulletin/instruct.txt differ
diff --git a/decus/vmslt98b/bulletin/login.com b/decus/vmslt98b/bulletin/login.com
new file mode 100755
index 0000000000000000000000000000000000000000..fa69c5013bb2f7098b438f3bf46245ab6ad14508
Binary files /dev/null and b/decus/vmslt98b/bulletin/login.com differ
diff --git a/decus/vmslt98b/bulletin/makefile b/decus/vmslt98b/bulletin/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..0efc9e5d138d3f30b889f54ad96c7553030443e7
Binary files /dev/null and b/decus/vmslt98b/bulletin/makefile differ
diff --git a/decus/vmslt98b/bulletin/master.com b/decus/vmslt98b/bulletin/master.com
new file mode 100755
index 0000000000000000000000000000000000000000..9f0e3178826024699704e0f689338a8d897fc9dc
Binary files /dev/null and b/decus/vmslt98b/bulletin/master.com differ
diff --git a/decus/vmslt98b/bulletin/mx.com b/decus/vmslt98b/bulletin/mx.com
new file mode 100755
index 0000000000000000000000000000000000000000..c971619ec2dc1df380672ba9175a662f94ad69e1
Binary files /dev/null and b/decus/vmslt98b/bulletin/mx.com differ
diff --git a/decus/vmslt98b/bulletin/mx.mai b/decus/vmslt98b/bulletin/mx.mai
new file mode 100755
index 0000000000000000000000000000000000000000..3eda561c65e4f42db3cdb6f8d79594eaaca2fefd
Binary files /dev/null and b/decus/vmslt98b/bulletin/mx.mai differ
diff --git a/decus/vmslt98b/bulletin/news.alt b/decus/vmslt98b/bulletin/news.alt
new file mode 100755
index 0000000000000000000000000000000000000000..ef71a6408372d85a7ccfcfb2251d50f75bde1ebe
Binary files /dev/null and b/decus/vmslt98b/bulletin/news.alt differ
diff --git a/decus/vmslt98b/bulletin/news.com b/decus/vmslt98b/bulletin/news.com
new file mode 100755
index 0000000000000000000000000000000000000000..1582a146c764cb5e2c2b163a5fa0940a0fb7c354
Binary files /dev/null and b/decus/vmslt98b/bulletin/news.com differ
diff --git a/decus/vmslt98b/bulletin/news.create b/decus/vmslt98b/bulletin/news.create
new file mode 100755
index 0000000000000000000000000000000000000000..b90a3d3650faea8ba7b4715a854f8085d12624c6
Binary files /dev/null and b/decus/vmslt98b/bulletin/news.create differ
diff --git a/decus/vmslt98b/bulletin/news.moderators b/decus/vmslt98b/bulletin/news.moderators
new file mode 100755
index 0000000000000000000000000000000000000000..b0f3d836093ce5085f63b6519aeaadc17f1626a8
Binary files /dev/null and b/decus/vmslt98b/bulletin/news.moderators differ
diff --git a/decus/vmslt98b/bulletin/news.txt b/decus/vmslt98b/bulletin/news.txt
new file mode 100755
index 0000000000000000000000000000000000000000..eb4969e8a639dfb85ec544d9df9416011198c13b
Binary files /dev/null and b/decus/vmslt98b/bulletin/news.txt differ
diff --git a/decus/vmslt98b/bulletin/nonsystem.txt b/decus/vmslt98b/bulletin/nonsystem.txt
new file mode 100755
index 0000000000000000000000000000000000000000..1c371fd8abc5c34f41319f98fe5bc942a390a9ed
Binary files /dev/null and b/decus/vmslt98b/bulletin/nonsystem.txt differ
diff --git a/decus/vmslt98b/bulletin/optimize_rms.com b/decus/vmslt98b/bulletin/optimize_rms.com
new file mode 100755
index 0000000000000000000000000000000000000000..1d3f04dbac9868f4468b3999e5e80a8b0d91a59c
Binary files /dev/null and b/decus/vmslt98b/bulletin/optimize_rms.com differ
diff --git a/decus/vmslt98b/bulletin/pmdf.com b/decus/vmslt98b/bulletin/pmdf.com
new file mode 100755
index 0000000000000000000000000000000000000000..c8bee3ce419823b003ddaa6edeb91ce56c6cce05
Binary files /dev/null and b/decus/vmslt98b/bulletin/pmdf.com differ
diff --git a/decus/vmslt98b/bulletin/restart.com b/decus/vmslt98b/bulletin/restart.com
new file mode 100755
index 0000000000000000000000000000000000000000..499764c5f0dc3b747c310de50039fa1b03071f17
Binary files /dev/null and b/decus/vmslt98b/bulletin/restart.com differ
diff --git a/decus/vmslt98b/bulletin/setuser.mar b/decus/vmslt98b/bulletin/setuser.mar
new file mode 100755
index 0000000000000000000000000000000000000000..bd3066dbdb50697071e10baed296cbdba9298f78
Binary files /dev/null and b/decus/vmslt98b/bulletin/setuser.mar differ
diff --git a/decus/vmslt98b/bulletin/update.fil b/decus/vmslt98b/bulletin/update.fil
new file mode 100755
index 0000000000000000000000000000000000000000..14b1c882c5fa8a6d7c244c38f1bd19bad6cb5041
Binary files /dev/null and b/decus/vmslt98b/bulletin/update.fil differ
diff --git a/decus/vmslt98b/bulletin/upgrade.com b/decus/vmslt98b/bulletin/upgrade.com
new file mode 100755
index 0000000000000000000000000000000000000000..d1f92d336b99b3517112d7177ced4d6f2d20ab12
Binary files /dev/null and b/decus/vmslt98b/bulletin/upgrade.com differ
diff --git a/decus/vmslt98b/bulletin/writemsg.txt b/decus/vmslt98b/bulletin/writemsg.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6ee4ec02e151fc32828c4e890830eee127cf5da3
Binary files /dev/null and b/decus/vmslt98b/bulletin/writemsg.txt differ